Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da06b46b authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/therm: cosmetic changes



This is purely preparation for upcoming commits, there should be no
code changes here.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 5a7d1e22
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@ enum nvkm_therm_attr_type {
};
};


struct nvkm_therm {
struct nvkm_therm {
	struct nvkm_subdev base;
	struct nvkm_subdev subdev;


	int (*pwm_ctrl)(struct nvkm_therm *, int line, bool);
	int (*pwm_ctrl)(struct nvkm_therm *, int line, bool);
	int (*pwm_get)(struct nvkm_therm *, int line, u32 *, u32 *);
	int (*pwm_get)(struct nvkm_therm *, int line, u32 *, u32 *);
@@ -50,16 +50,16 @@ nvkm_therm(void *obj)
#define nvkm_therm_create(p,e,o,d)                                          \
#define nvkm_therm_create(p,e,o,d)                                          \
	nvkm_therm_create_((p), (e), (o), sizeof(**d), (void **)d)
	nvkm_therm_create_((p), (e), (o), sizeof(**d), (void **)d)
#define nvkm_therm_destroy(p) ({                                            \
#define nvkm_therm_destroy(p) ({                                            \
	struct nvkm_therm *therm = (p);                                     \
	struct nvkm_therm *_therm = (p);                                     \
        _nvkm_therm_dtor(nv_object(therm));                                 \
        _nvkm_therm_dtor(nv_object(_therm));                                 \
})
})
#define nvkm_therm_init(p) ({                                               \
#define nvkm_therm_init(p) ({                                               \
	struct nvkm_therm *therm = (p);                                     \
	struct nvkm_therm *_therm = (p);                                     \
        _nvkm_therm_init(nv_object(therm));                                 \
        _nvkm_therm_init(nv_object(_therm));                                 \
})
})
#define nvkm_therm_fini(p,s) ({                                             \
#define nvkm_therm_fini(p,s) ({                                             \
	struct nvkm_therm *therm = (p);                                     \
	struct nvkm_therm *_therm = (p);                                     \
        _nvkm_therm_init(nv_object(therm), (s));                            \
        _nvkm_therm_init(nv_object(_therm), (s));                            \
})
})


int  nvkm_therm_create_(struct nvkm_object *, struct nvkm_object *,
int  nvkm_therm_create_(struct nvkm_object *, struct nvkm_object *,
+5 −5
Original line number Original line Diff line number Diff line
@@ -76,7 +76,7 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust,
static int
static int
nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
{
{
	struct nvkm_therm *ptherm = nvkm_therm(clk);
	struct nvkm_therm *therm = nvkm_therm(clk);
	struct nvkm_volt *volt = nvkm_volt(clk);
	struct nvkm_volt *volt = nvkm_volt(clk);
	struct nvkm_cstate *cstate;
	struct nvkm_cstate *cstate;
	int ret;
	int ret;
@@ -87,8 +87,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
		cstate = &pstate->base;
		cstate = &pstate->base;
	}
	}


	if (ptherm) {
	if (therm) {
		ret = nvkm_therm_cstate(ptherm, pstate->fanspeed, +1);
		ret = nvkm_therm_cstate(therm, pstate->fanspeed, +1);
		if (ret && ret != -ENODEV) {
		if (ret && ret != -ENODEV) {
			nv_error(clk, "failed to raise fan speed: %d\n", ret);
			nv_error(clk, "failed to raise fan speed: %d\n", ret);
			return ret;
			return ret;
@@ -115,8 +115,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
			nv_error(clk, "failed to lower voltage: %d\n", ret);
			nv_error(clk, "failed to lower voltage: %d\n", ret);
	}
	}


	if (ptherm) {
	if (therm) {
		ret = nvkm_therm_cstate(ptherm, pstate->fanspeed, -1);
		ret = nvkm_therm_cstate(therm, pstate->fanspeed, -1);
		if (ret && ret != -ENODEV)
		if (ret && ret != -ENODEV)
			nv_error(clk, "failed to lower fan speed: %d\n", ret);
			nv_error(clk, "failed to lower fan speed: %d\n", ret);
	}
	}
+115 −117
Original line number Original line Diff line number Diff line
@@ -24,18 +24,18 @@
#include "priv.h"
#include "priv.h"


static int
static int
nvkm_therm_update_trip(struct nvkm_therm *therm)
nvkm_therm_update_trip(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvbios_therm_trip_point *trip = priv->fan->bios.trip,
	struct nvbios_therm_trip_point *trip = therm->fan->bios.trip,
				       *cur_trip = NULL,
				       *cur_trip = NULL,
				       *last_trip = priv->last_trip;
				       *last_trip = therm->last_trip;
	u8  temp = therm->temp_get(therm);
	u8  temp = therm->base.temp_get(&therm->base);
	u16 duty, i;
	u16 duty, i;


	/* look for the trip point corresponding to the current temperature */
	/* look for the trip point corresponding to the current temperature */
	cur_trip = NULL;
	cur_trip = NULL;
	for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) {
	for (i = 0; i < therm->fan->bios.nr_fan_trip; i++) {
		if (temp >= trip[i].temp)
		if (temp >= trip[i].temp)
			cur_trip = &trip[i];
			cur_trip = &trip[i];
	}
	}
@@ -47,72 +47,72 @@ nvkm_therm_update_trip(struct nvkm_therm *therm)


	if (cur_trip) {
	if (cur_trip) {
		duty = cur_trip->fan_duty;
		duty = cur_trip->fan_duty;
		priv->last_trip = cur_trip;
		therm->last_trip = cur_trip;
	} else {
	} else {
		duty = 0;
		duty = 0;
		priv->last_trip = NULL;
		therm->last_trip = NULL;
	}
	}


	return duty;
	return duty;
}
}


static int
static int
nvkm_therm_update_linear(struct nvkm_therm *therm)
nvkm_therm_update_linear(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	u8  linear_min_temp = priv->fan->bios.linear_min_temp;
	u8  linear_min_temp = therm->fan->bios.linear_min_temp;
	u8  linear_max_temp = priv->fan->bios.linear_max_temp;
	u8  linear_max_temp = therm->fan->bios.linear_max_temp;
	u8  temp = therm->temp_get(therm);
	u8  temp = therm->base.temp_get(&therm->base);
	u16 duty;
	u16 duty;


	/* handle the non-linear part first */
	/* handle the non-linear part first */
	if (temp < linear_min_temp)
	if (temp < linear_min_temp)
		return priv->fan->bios.min_duty;
		return therm->fan->bios.min_duty;
	else if (temp > linear_max_temp)
	else if (temp > linear_max_temp)
		return priv->fan->bios.max_duty;
		return therm->fan->bios.max_duty;


	/* we are in the linear zone */
	/* we are in the linear zone */
	duty  = (temp - linear_min_temp);
	duty  = (temp - linear_min_temp);
	duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty);
	duty *= (therm->fan->bios.max_duty - therm->fan->bios.min_duty);
	duty /= (linear_max_temp - linear_min_temp);
	duty /= (linear_max_temp - linear_min_temp);
	duty += priv->fan->bios.min_duty;
	duty += therm->fan->bios.min_duty;
	return duty;
	return duty;
}
}


static void
static void
nvkm_therm_update(struct nvkm_therm *therm, int mode)
nvkm_therm_update(struct nvkm_therm *obj, int mode)
{
{
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_therm_priv *priv = (void *)therm;
	unsigned long flags;
	unsigned long flags;
	bool immd = true;
	bool immd = true;
	bool poll = true;
	bool poll = true;
	int duty = -1;
	int duty = -1;


	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irqsave(&therm->lock, flags);
	if (mode < 0)
	if (mode < 0)
		mode = priv->mode;
		mode = therm->mode;
	priv->mode = mode;
	therm->mode = mode;


	switch (mode) {
	switch (mode) {
	case NVKM_THERM_CTRL_MANUAL:
	case NVKM_THERM_CTRL_MANUAL:
		ptimer->alarm_cancel(ptimer, &priv->alarm);
		ptimer->alarm_cancel(ptimer, &therm->alarm);
		duty = nvkm_therm_fan_get(therm);
		duty = nvkm_therm_fan_get(&therm->base);
		if (duty < 0)
		if (duty < 0)
			duty = 100;
			duty = 100;
		poll = false;
		poll = false;
		break;
		break;
	case NVKM_THERM_CTRL_AUTO:
	case NVKM_THERM_CTRL_AUTO:
		switch(priv->fan->bios.fan_mode) {
		switch(therm->fan->bios.fan_mode) {
		case NVBIOS_THERM_FAN_TRIP:
		case NVBIOS_THERM_FAN_TRIP:
			duty = nvkm_therm_update_trip(therm);
			duty = nvkm_therm_update_trip(&therm->base);
			break;
			break;
		case NVBIOS_THERM_FAN_LINEAR:
		case NVBIOS_THERM_FAN_LINEAR:
			duty = nvkm_therm_update_linear(therm);
			duty = nvkm_therm_update_linear(&therm->base);
			break;
			break;
		case NVBIOS_THERM_FAN_OTHER:
		case NVBIOS_THERM_FAN_OTHER:
			if (priv->cstate)
			if (therm->cstate)
				duty = priv->cstate;
				duty = therm->cstate;
			poll = false;
			poll = false;
			break;
			break;
		}
		}
@@ -120,29 +120,29 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
		break;
		break;
	case NVKM_THERM_CTRL_NONE:
	case NVKM_THERM_CTRL_NONE:
	default:
	default:
		ptimer->alarm_cancel(ptimer, &priv->alarm);
		ptimer->alarm_cancel(ptimer, &therm->alarm);
		poll = false;
		poll = false;
	}
	}


	if (list_empty(&priv->alarm.head) && poll)
	if (list_empty(&therm->alarm.head) && poll)
		ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
		ptimer->alarm(ptimer, 1000000000ULL, &therm->alarm);
	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irqrestore(&therm->lock, flags);


	if (duty >= 0) {
	if (duty >= 0) {
		nv_debug(therm, "FAN target request: %d%%\n", duty);
		nv_debug(therm, "FAN target request: %d%%\n", duty);
		nvkm_therm_fan_set(therm, immd, duty);
		nvkm_therm_fan_set(&therm->base, immd, duty);
	}
	}
}
}


int
int
nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir)
nvkm_therm_cstate(struct nvkm_therm *obj, int fan, int dir)
{
{
	struct nvkm_therm_priv *priv = (void *)ptherm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	if (!dir || (dir < 0 && fan < priv->cstate) ||
	if (!dir || (dir < 0 && fan < therm->cstate) ||
		    (dir > 0 && fan > priv->cstate)) {
		    (dir > 0 && fan > therm->cstate)) {
		nv_debug(ptherm, "default fan speed -> %d%%\n", fan);
		nv_debug(therm, "default fan speed -> %d%%\n", fan);
		priv->cstate = fan;
		therm->cstate = fan;
		nvkm_therm_update(ptherm, -1);
		nvkm_therm_update(&therm->base, -1);
	}
	}
	return 0;
	return 0;
}
}
@@ -150,15 +150,15 @@ nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir)
static void
static void
nvkm_therm_alarm(struct nvkm_alarm *alarm)
nvkm_therm_alarm(struct nvkm_alarm *alarm)
{
{
	struct nvkm_therm_priv *priv =
	struct nvkm_therm_priv *therm =
	       container_of(alarm, struct nvkm_therm_priv, alarm);
	       container_of(alarm, struct nvkm_therm_priv, alarm);
	nvkm_therm_update(&priv->base, -1);
	nvkm_therm_update(&therm->base, -1);
}
}


int
int
nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode)
nvkm_therm_fan_mode(struct nvkm_therm *obj, int mode)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_device *device = nv_device(therm);
	struct nvkm_device *device = nv_device(therm);
	static const char *name[] = {
	static const char *name[] = {
		"disabled",
		"disabled",
@@ -174,105 +174,105 @@ nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode)


	/* do not allow automatic fan management if the thermal sensor is
	/* do not allow automatic fan management if the thermal sensor is
	 * not available */
	 * not available */
	if (mode == NVKM_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)
	if (mode == NVKM_THERM_CTRL_AUTO &&
	    therm->base.temp_get(&therm->base) < 0)
		return -EINVAL;
		return -EINVAL;


	if (priv->mode == mode)
	if (therm->mode == mode)
		return 0;
		return 0;


	nv_info(therm, "fan management: %s\n", name[mode]);
	nv_info(therm, "fan management: %s\n", name[mode]);
	nvkm_therm_update(therm, mode);
	nvkm_therm_update(&therm->base, mode);
	return 0;
	return 0;
}
}


int
int
nvkm_therm_attr_get(struct nvkm_therm *therm,
nvkm_therm_attr_get(struct nvkm_therm *obj, enum nvkm_therm_attr_type type)
		       enum nvkm_therm_attr_type type)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);


	switch (type) {
	switch (type) {
	case NVKM_THERM_ATTR_FAN_MIN_DUTY:
	case NVKM_THERM_ATTR_FAN_MIN_DUTY:
		return priv->fan->bios.min_duty;
		return therm->fan->bios.min_duty;
	case NVKM_THERM_ATTR_FAN_MAX_DUTY:
	case NVKM_THERM_ATTR_FAN_MAX_DUTY:
		return priv->fan->bios.max_duty;
		return therm->fan->bios.max_duty;
	case NVKM_THERM_ATTR_FAN_MODE:
	case NVKM_THERM_ATTR_FAN_MODE:
		return priv->mode;
		return therm->mode;
	case NVKM_THERM_ATTR_THRS_FAN_BOOST:
	case NVKM_THERM_ATTR_THRS_FAN_BOOST:
		return priv->bios_sensor.thrs_fan_boost.temp;
		return therm->bios_sensor.thrs_fan_boost.temp;
	case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
	case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
		return priv->bios_sensor.thrs_fan_boost.hysteresis;
		return therm->bios_sensor.thrs_fan_boost.hysteresis;
	case NVKM_THERM_ATTR_THRS_DOWN_CLK:
	case NVKM_THERM_ATTR_THRS_DOWN_CLK:
		return priv->bios_sensor.thrs_down_clock.temp;
		return therm->bios_sensor.thrs_down_clock.temp;
	case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
	case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
		return priv->bios_sensor.thrs_down_clock.hysteresis;
		return therm->bios_sensor.thrs_down_clock.hysteresis;
	case NVKM_THERM_ATTR_THRS_CRITICAL:
	case NVKM_THERM_ATTR_THRS_CRITICAL:
		return priv->bios_sensor.thrs_critical.temp;
		return therm->bios_sensor.thrs_critical.temp;
	case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
	case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
		return priv->bios_sensor.thrs_critical.hysteresis;
		return therm->bios_sensor.thrs_critical.hysteresis;
	case NVKM_THERM_ATTR_THRS_SHUTDOWN:
	case NVKM_THERM_ATTR_THRS_SHUTDOWN:
		return priv->bios_sensor.thrs_shutdown.temp;
		return therm->bios_sensor.thrs_shutdown.temp;
	case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
	case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
		return priv->bios_sensor.thrs_shutdown.hysteresis;
		return therm->bios_sensor.thrs_shutdown.hysteresis;
	}
	}


	return -EINVAL;
	return -EINVAL;
}
}


int
int
nvkm_therm_attr_set(struct nvkm_therm *therm,
nvkm_therm_attr_set(struct nvkm_therm *obj,
		    enum nvkm_therm_attr_type type, int value)
		    enum nvkm_therm_attr_type type, int value)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);


	switch (type) {
	switch (type) {
	case NVKM_THERM_ATTR_FAN_MIN_DUTY:
	case NVKM_THERM_ATTR_FAN_MIN_DUTY:
		if (value < 0)
		if (value < 0)
			value = 0;
			value = 0;
		if (value > priv->fan->bios.max_duty)
		if (value > therm->fan->bios.max_duty)
			value = priv->fan->bios.max_duty;
			value = therm->fan->bios.max_duty;
		priv->fan->bios.min_duty = value;
		therm->fan->bios.min_duty = value;
		return 0;
		return 0;
	case NVKM_THERM_ATTR_FAN_MAX_DUTY:
	case NVKM_THERM_ATTR_FAN_MAX_DUTY:
		if (value < 0)
		if (value < 0)
			value = 0;
			value = 0;
		if (value < priv->fan->bios.min_duty)
		if (value < therm->fan->bios.min_duty)
			value = priv->fan->bios.min_duty;
			value = therm->fan->bios.min_duty;
		priv->fan->bios.max_duty = value;
		therm->fan->bios.max_duty = value;
		return 0;
		return 0;
	case NVKM_THERM_ATTR_FAN_MODE:
	case NVKM_THERM_ATTR_FAN_MODE:
		return nvkm_therm_fan_mode(therm, value);
		return nvkm_therm_fan_mode(&therm->base, value);
	case NVKM_THERM_ATTR_THRS_FAN_BOOST:
	case NVKM_THERM_ATTR_THRS_FAN_BOOST:
		priv->bios_sensor.thrs_fan_boost.temp = value;
		therm->bios_sensor.thrs_fan_boost.temp = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
	case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST:
		priv->bios_sensor.thrs_fan_boost.hysteresis = value;
		therm->bios_sensor.thrs_fan_boost.hysteresis = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_DOWN_CLK:
	case NVKM_THERM_ATTR_THRS_DOWN_CLK:
		priv->bios_sensor.thrs_down_clock.temp = value;
		therm->bios_sensor.thrs_down_clock.temp = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
	case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST:
		priv->bios_sensor.thrs_down_clock.hysteresis = value;
		therm->bios_sensor.thrs_down_clock.hysteresis = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_CRITICAL:
	case NVKM_THERM_ATTR_THRS_CRITICAL:
		priv->bios_sensor.thrs_critical.temp = value;
		therm->bios_sensor.thrs_critical.temp = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
	case NVKM_THERM_ATTR_THRS_CRITICAL_HYST:
		priv->bios_sensor.thrs_critical.hysteresis = value;
		therm->bios_sensor.thrs_critical.hysteresis = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_SHUTDOWN:
	case NVKM_THERM_ATTR_THRS_SHUTDOWN:
		priv->bios_sensor.thrs_shutdown.temp = value;
		therm->bios_sensor.thrs_shutdown.temp = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
	case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST:
		priv->bios_sensor.thrs_shutdown.hysteresis = value;
		therm->bios_sensor.thrs_shutdown.hysteresis = value;
		priv->sensor.program_alarms(therm);
		therm->sensor.program_alarms(&therm->base);
		return 0;
		return 0;
	}
	}


@@ -282,65 +282,63 @@ nvkm_therm_attr_set(struct nvkm_therm *therm,
int
int
_nvkm_therm_init(struct nvkm_object *object)
_nvkm_therm_init(struct nvkm_object *object)
{
{
	struct nvkm_therm *therm = (void *)object;
	struct nvkm_therm_priv *therm = (void *)object;
	struct nvkm_therm_priv *priv = (void *)therm;
	int ret;
	int ret;


	ret = nvkm_subdev_init(&therm->base);
	ret = nvkm_subdev_init(&therm->base.subdev);
	if (ret)
	if (ret)
		return ret;
		return ret;


	if (priv->suspend >= 0) {
	if (therm->suspend >= 0) {
		/* restore the pwm value only when on manual or auto mode */
		/* restore the pwm value only when on manual or auto mode */
		if (priv->suspend > 0)
		if (therm->suspend > 0)
			nvkm_therm_fan_set(therm, true, priv->fan->percent);
			nvkm_therm_fan_set(&therm->base, true, therm->fan->percent);


		nvkm_therm_fan_mode(therm, priv->suspend);
		nvkm_therm_fan_mode(&therm->base, therm->suspend);
	}
	}
	nvkm_therm_sensor_init(therm);
	nvkm_therm_sensor_init(&therm->base);
	nvkm_therm_fan_init(therm);
	nvkm_therm_fan_init(&therm->base);
	return 0;
	return 0;
}
}


int
int
_nvkm_therm_fini(struct nvkm_object *object, bool suspend)
_nvkm_therm_fini(struct nvkm_object *object, bool suspend)
{
{
	struct nvkm_therm *therm = (void *)object;
	struct nvkm_therm_priv *therm = (void *)object;
	struct nvkm_therm_priv *priv = (void *)therm;


	nvkm_therm_fan_fini(therm, suspend);
	nvkm_therm_fan_fini(&therm->base, suspend);
	nvkm_therm_sensor_fini(therm, suspend);
	nvkm_therm_sensor_fini(&therm->base, suspend);
	if (suspend) {
	if (suspend) {
		priv->suspend = priv->mode;
		therm->suspend = therm->mode;
		priv->mode = NVKM_THERM_CTRL_NONE;
		therm->mode = NVKM_THERM_CTRL_NONE;
	}
	}


	return nvkm_subdev_fini(&therm->base, suspend);
	return nvkm_subdev_fini(&therm->base.subdev, suspend);
}
}


int
int
nvkm_therm_create_(struct nvkm_object *parent, struct nvkm_object *engine,
nvkm_therm_create_(struct nvkm_object *parent, struct nvkm_object *engine,
		   struct nvkm_oclass *oclass, int length, void **pobject)
		   struct nvkm_oclass *oclass, int length, void **pobject)
{
{
	struct nvkm_therm_priv *priv;
	struct nvkm_therm_priv *therm;
	int ret;
	int ret;


	ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PTHERM",
	ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PTHERM",
				  "therm", length, pobject);
				  "therm", length, pobject);
	priv = *pobject;
	therm = *pobject;
	if (ret)
	if (ret)
		return ret;
		return ret;


	nvkm_alarm_init(&priv->alarm, nvkm_therm_alarm);
	nvkm_alarm_init(&therm->alarm, nvkm_therm_alarm);
	spin_lock_init(&priv->lock);
	spin_lock_init(&therm->lock);
	spin_lock_init(&priv->sensor.alarm_program_lock);
	spin_lock_init(&therm->sensor.alarm_program_lock);


	priv->base.fan_get = nvkm_therm_fan_user_get;
	therm->base.fan_get = nvkm_therm_fan_user_get;
	priv->base.fan_set = nvkm_therm_fan_user_set;
	therm->base.fan_set = nvkm_therm_fan_user_set;
	priv->base.fan_sense = nvkm_therm_fan_sense;
	therm->base.fan_sense = nvkm_therm_fan_sense;
	priv->base.attr_get = nvkm_therm_attr_get;
	therm->base.attr_get = nvkm_therm_attr_get;
	priv->base.attr_set = nvkm_therm_attr_set;
	therm->base.attr_set = nvkm_therm_attr_set;
	priv->mode = priv->suspend = -1; /* undefined */
	therm->mode = therm->suspend = -1; /* undefined */
	return 0;
	return 0;
}
}


@@ -359,7 +357,7 @@ nvkm_therm_preinit(struct nvkm_therm *therm)
void
void
_nvkm_therm_dtor(struct nvkm_object *object)
_nvkm_therm_dtor(struct nvkm_object *object)
{
{
	struct nvkm_therm_priv *priv = (void *)object;
	struct nvkm_therm_priv *therm = (void *)object;
	kfree(priv->fan);
	kfree(therm->fan);
	nvkm_subdev_destroy(&priv->base.base);
	nvkm_subdev_destroy(&therm->base.subdev);
}
}
+61 −61
Original line number Original line Diff line number Diff line
@@ -31,9 +31,8 @@
static int
static int
nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
{
{
	struct nvkm_therm *therm = fan->parent;
	struct nvkm_therm_priv *therm = (void *)fan->parent;
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_timer *ptimer = nvkm_timer(priv);
	unsigned long flags;
	unsigned long flags;
	int ret = 0;
	int ret = 0;
	int duty;
	int duty;
@@ -50,7 +49,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
	}
	}


	/* check that we're not already at the target duty cycle */
	/* check that we're not already at the target duty cycle */
	duty = fan->get(therm);
	duty = fan->get(&therm->base);
	if (duty == target) {
	if (duty == target) {
		spin_unlock_irqrestore(&fan->lock, flags);
		spin_unlock_irqrestore(&fan->lock, flags);
		return 0;
		return 0;
@@ -71,7 +70,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
	}
	}


	nv_debug(therm, "FAN update: %d\n", duty);
	nv_debug(therm, "FAN update: %d\n", duty);
	ret = fan->set(therm, duty);
	ret = fan->set(&therm->base, duty);
	if (ret) {
	if (ret) {
		spin_unlock_irqrestore(&fan->lock, flags);
		spin_unlock_irqrestore(&fan->lock, flags);
		return ret;
		return ret;
@@ -109,29 +108,29 @@ nvkm_fan_alarm(struct nvkm_alarm *alarm)
}
}


int
int
nvkm_therm_fan_get(struct nvkm_therm *therm)
nvkm_therm_fan_get(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	return priv->fan->get(therm);
	return therm->fan->get(&therm->base);
}
}


int
int
nvkm_therm_fan_set(struct nvkm_therm *therm, bool immediate, int percent)
nvkm_therm_fan_set(struct nvkm_therm *obj, bool immediate, int percent)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	return nvkm_fan_update(priv->fan, immediate, percent);
	return nvkm_fan_update(therm->fan, immediate, percent);
}
}


int
int
nvkm_therm_fan_sense(struct nvkm_therm *therm)
nvkm_therm_fan_sense(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_gpio *gpio = nvkm_gpio(therm);
	struct nvkm_gpio *gpio = nvkm_gpio(therm);
	u32 cycles, cur, prev;
	u32 cycles, cur, prev;
	u64 start, end, tach;
	u64 start, end, tach;


	if (priv->fan->tach.func == DCB_GPIO_UNUSED)
	if (therm->fan->tach.func == DCB_GPIO_UNUSED)
		return -ENODEV;
		return -ENODEV;


	/* Time a complete rotation and extrapolate to RPM:
	/* Time a complete rotation and extrapolate to RPM:
@@ -139,12 +138,12 @@ nvkm_therm_fan_sense(struct nvkm_therm *therm)
	 * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation.
	 * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation.
	 */
	 */
	start = ptimer->read(ptimer);
	start = ptimer->read(ptimer);
	prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
	prev = gpio->get(gpio, 0, therm->fan->tach.func, therm->fan->tach.line);
	cycles = 0;
	cycles = 0;
	do {
	do {
		usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
		usleep_range(500, 1000); /* supports 0 < rpm < 7500 */


		cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
		cur = gpio->get(gpio, 0, therm->fan->tach.func, therm->fan->tach.line);
		if (prev != cur) {
		if (prev != cur) {
			if (!start)
			if (!start)
				start = ptimer->read(ptimer);
				start = ptimer->read(ptimer);
@@ -163,71 +162,72 @@ nvkm_therm_fan_sense(struct nvkm_therm *therm)
}
}


int
int
nvkm_therm_fan_user_get(struct nvkm_therm *therm)
nvkm_therm_fan_user_get(struct nvkm_therm *obj)
{
{
	return nvkm_therm_fan_get(therm);
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	return nvkm_therm_fan_get(&therm->base);
}
}


int
int
nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent)
nvkm_therm_fan_user_set(struct nvkm_therm *obj, int percent)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);


	if (priv->mode != NVKM_THERM_CTRL_MANUAL)
	if (therm->mode != NVKM_THERM_CTRL_MANUAL)
		return -EINVAL;
		return -EINVAL;


	return nvkm_therm_fan_set(therm, true, percent);
	return nvkm_therm_fan_set(&therm->base, true, percent);
}
}


static void
static void
nvkm_therm_fan_set_defaults(struct nvkm_therm *therm)
nvkm_therm_fan_set_defaults(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);


	priv->fan->bios.pwm_freq = 0;
	therm->fan->bios.pwm_freq = 0;
	priv->fan->bios.min_duty = 0;
	therm->fan->bios.min_duty = 0;
	priv->fan->bios.max_duty = 100;
	therm->fan->bios.max_duty = 100;
	priv->fan->bios.bump_period = 500;
	therm->fan->bios.bump_period = 500;
	priv->fan->bios.slow_down_period = 2000;
	therm->fan->bios.slow_down_period = 2000;
	priv->fan->bios.linear_min_temp = 40;
	therm->fan->bios.linear_min_temp = 40;
	priv->fan->bios.linear_max_temp = 85;
	therm->fan->bios.linear_max_temp = 85;
}
}


static void
static void
nvkm_therm_fan_safety_checks(struct nvkm_therm *therm)
nvkm_therm_fan_safety_checks(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);


	if (priv->fan->bios.min_duty > 100)
	if (therm->fan->bios.min_duty > 100)
		priv->fan->bios.min_duty = 100;
		therm->fan->bios.min_duty = 100;
	if (priv->fan->bios.max_duty > 100)
	if (therm->fan->bios.max_duty > 100)
		priv->fan->bios.max_duty = 100;
		therm->fan->bios.max_duty = 100;


	if (priv->fan->bios.min_duty > priv->fan->bios.max_duty)
	if (therm->fan->bios.min_duty > therm->fan->bios.max_duty)
		priv->fan->bios.min_duty = priv->fan->bios.max_duty;
		therm->fan->bios.min_duty = therm->fan->bios.max_duty;
}
}


int
int
nvkm_therm_fan_init(struct nvkm_therm *therm)
nvkm_therm_fan_init(struct nvkm_therm *obj)
{
{
	return 0;
	return 0;
}
}


int
int
nvkm_therm_fan_fini(struct nvkm_therm *therm, bool suspend)
nvkm_therm_fan_fini(struct nvkm_therm *obj, bool suspend)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_timer *ptimer = nvkm_timer(therm);
	struct nvkm_timer *ptimer = nvkm_timer(therm);


	if (suspend)
	if (suspend)
		ptimer->alarm_cancel(ptimer, &priv->fan->alarm);
		ptimer->alarm_cancel(ptimer, &therm->fan->alarm);
	return 0;
	return 0;
}
}


int
int
nvkm_therm_fan_ctor(struct nvkm_therm *therm)
nvkm_therm_fan_ctor(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *priv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_gpio *gpio = nvkm_gpio(therm);
	struct nvkm_gpio *gpio = nvkm_gpio(therm);
	struct nvkm_bios *bios = nvkm_bios(therm);
	struct nvkm_bios *bios = nvkm_bios(therm);
	struct dcb_gpio_func func;
	struct dcb_gpio_func func;
@@ -241,42 +241,42 @@ nvkm_therm_fan_ctor(struct nvkm_therm *therm)
			nv_debug(therm, "GPIO_FAN is in input mode\n");
			nv_debug(therm, "GPIO_FAN is in input mode\n");
			ret = -EINVAL;
			ret = -EINVAL;
		} else {
		} else {
			ret = nvkm_fanpwm_create(therm, &func);
			ret = nvkm_fanpwm_create(&therm->base, &func);
			if (ret != 0)
			if (ret != 0)
				ret = nvkm_fantog_create(therm, &func);
				ret = nvkm_fantog_create(&therm->base, &func);
		}
		}
	}
	}


	/* no controllable fan found, create a dummy fan module */
	/* no controllable fan found, create a dummy fan module */
	if (ret != 0) {
	if (ret != 0) {
		ret = nvkm_fannil_create(therm);
		ret = nvkm_fannil_create(&therm->base);
		if (ret)
		if (ret)
			return ret;
			return ret;
	}
	}


	nv_info(therm, "FAN control: %s\n", priv->fan->type);
	nv_info(therm, "FAN control: %s\n", therm->fan->type);


	/* read the current speed, it is useful when resuming */
	/* read the current speed, it is useful when resuming */
	priv->fan->percent = nvkm_therm_fan_get(therm);
	therm->fan->percent = nvkm_therm_fan_get(&therm->base);


	/* attempt to detect a tachometer connection */
	/* attempt to detect a tachometer connection */
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach);
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &therm->fan->tach);
	if (ret)
	if (ret)
		priv->fan->tach.func = DCB_GPIO_UNUSED;
		therm->fan->tach.func = DCB_GPIO_UNUSED;


	/* initialise fan bump/slow update handling */
	/* initialise fan bump/slow update handling */
	priv->fan->parent = therm;
	therm->fan->parent = &therm->base;
	nvkm_alarm_init(&priv->fan->alarm, nvkm_fan_alarm);
	nvkm_alarm_init(&therm->fan->alarm, nvkm_fan_alarm);
	spin_lock_init(&priv->fan->lock);
	spin_lock_init(&therm->fan->lock);


	/* other random init... */
	/* other random init... */
	nvkm_therm_fan_set_defaults(therm);
	nvkm_therm_fan_set_defaults(&therm->base);
	nvbios_perf_fan_parse(bios, &priv->fan->perf);
	nvbios_perf_fan_parse(bios, &therm->fan->perf);
	if (!nvbios_fan_parse(bios, &priv->fan->bios)) {
	if (!nvbios_fan_parse(bios, &therm->fan->bios)) {
		nv_debug(therm, "parsing the fan table failed\n");
		nv_debug(therm, "parsing the fan table failed\n");
		if (nvbios_therm_fan_parse(bios, &priv->fan->bios))
		if (nvbios_therm_fan_parse(bios, &therm->fan->bios))
			nv_error(therm, "parsing both fan tables failed\n");
			nv_error(therm, "parsing both fan tables failed\n");
	}
	}
	nvkm_therm_fan_safety_checks(therm);
	nvkm_therm_fan_safety_checks(&therm->base);
	return 0;
	return 0;
}
}
+3 −3
Original line number Original line Diff line number Diff line
@@ -36,13 +36,13 @@ nvkm_fannil_set(struct nvkm_therm *therm, int percent)
}
}


int
int
nvkm_fannil_create(struct nvkm_therm *therm)
nvkm_fannil_create(struct nvkm_therm *obj)
{
{
	struct nvkm_therm_priv *tpriv = (void *)therm;
	struct nvkm_therm_priv *therm = container_of(obj, typeof(*therm), base);
	struct nvkm_fan *priv;
	struct nvkm_fan *priv;


	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	tpriv->fan = priv;
	therm->fan = priv;
	if (!priv)
	if (!priv)
		return -ENOMEM;
		return -ENOMEM;


Loading