Commit 1a22274b authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/therm: better transitions and debug logging

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarMartin Peres <martin.peres@labri.fr>
parent 041d6246
...@@ -4,11 +4,10 @@ ...@@ -4,11 +4,10 @@
#include <core/device.h> #include <core/device.h>
#include <core/subdev.h> #include <core/subdev.h>
enum nouveau_therm_fan_mode { enum nouveau_therm_mode {
FAN_CONTROL_NONE = 0, NOUVEAU_THERM_CTRL_NONE = 0,
FAN_CONTROL_MANUAL = 1, NOUVEAU_THERM_CTRL_MANUAL = 1,
FAN_CONTROL_AUTO = 2, NOUVEAU_THERM_CTRL_AUTO = 2,
FAN_CONTROL_NR,
}; };
enum nouveau_therm_attr_type { enum nouveau_therm_attr_type {
......
...@@ -93,24 +93,27 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) ...@@ -93,24 +93,27 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
priv->mode = mode; priv->mode = mode;
switch (mode) { switch (mode) {
case FAN_CONTROL_MANUAL: case NOUVEAU_THERM_CTRL_MANUAL:
duty = priv->fan->percent; duty = nouveau_therm_fan_get(therm);
if (duty < 0)
duty = 100;
break; break;
case FAN_CONTROL_AUTO: case NOUVEAU_THERM_CTRL_AUTO:
if (priv->fan->bios.nr_fan_trip) if (priv->fan->bios.nr_fan_trip)
duty = nouveau_therm_update_trip(therm); duty = nouveau_therm_update_trip(therm);
else else
duty = nouveau_therm_update_linear(therm); duty = nouveau_therm_update_linear(therm);
break; break;
case FAN_CONTROL_NONE: case NOUVEAU_THERM_CTRL_NONE:
default: default:
goto done; goto done;
} }
nouveau_therm_fan_set(therm, (mode != FAN_CONTROL_AUTO), duty); nv_debug(therm, "FAN target request: %d%%\n", duty);
nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty);
done: done:
if (list_empty(&priv->alarm.head) && (mode == FAN_CONTROL_AUTO)) if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO))
ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
...@@ -127,28 +130,22 @@ int ...@@ -127,28 +130,22 @@ int
nouveau_therm_mode(struct nouveau_therm *therm, int mode) nouveau_therm_mode(struct nouveau_therm *therm, int mode)
{ {
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
struct nouveau_device *device = nv_device(therm);
if (priv->mode == mode) static const char *name[] = {
return 0; "disabled",
"manual",
"automatic"
};
/* The default PDAEMON ucode interferes with fan management */ /* The default PDAEMON ucode interferes with fan management */
if (nv_device(therm)->card_type >= NV_C0) if ((mode >= ARRAY_SIZE(name)) ||
(mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
return -EINVAL; return -EINVAL;
switch (mode) { if (priv->mode == mode)
case FAN_CONTROL_NONE: return 0;
nv_info(therm, "switch to no-control mode\n");
break;
case FAN_CONTROL_MANUAL:
nv_info(therm, "switch to manual mode\n");
break;
case FAN_CONTROL_AUTO:
nv_info(therm, "switch to automatic mode\n");
break;
default:
return -EINVAL;
}
nv_info(therm, "Thermal management: %s\n", name[mode]);
nouveau_therm_update(therm, mode); nouveau_therm_update(therm, mode);
return 0; return 0;
} }
...@@ -258,9 +255,8 @@ _nouveau_therm_init(struct nouveau_object *object) ...@@ -258,9 +255,8 @@ _nouveau_therm_init(struct nouveau_object *object)
if (ret) if (ret)
return ret; return ret;
if (priv->fan->percent >= 0) if (priv->suspend >= 0)
therm->fan_set(therm, priv->fan->percent); nouveau_therm_mode(therm, priv->mode);
priv->sensor.program_alarms(therm); priv->sensor.program_alarms(therm);
return 0; return 0;
} }
...@@ -271,7 +267,10 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend) ...@@ -271,7 +267,10 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend)
struct nouveau_therm *therm = (void *)object; struct nouveau_therm *therm = (void *)object;
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
priv->fan->percent = therm->fan_get(therm); if (suspend) {
priv->suspend = priv->mode;
priv->mode = NOUVEAU_THERM_CTRL_NONE;
}
return nouveau_subdev_fini(&therm->base, suspend); return nouveau_subdev_fini(&therm->base, suspend);
} }
...@@ -299,6 +298,7 @@ nouveau_therm_create_(struct nouveau_object *parent, ...@@ -299,6 +298,7 @@ nouveau_therm_create_(struct nouveau_object *parent,
priv->base.fan_sense = nouveau_therm_fan_sense; priv->base.fan_sense = nouveau_therm_fan_sense;
priv->base.attr_get = nouveau_therm_attr_get; priv->base.attr_get = nouveau_therm_attr_get;
priv->base.attr_set = nouveau_therm_attr_set; priv->base.attr_set = nouveau_therm_attr_set;
priv->mode = priv->suspend = -1; /* undefined */
return 0; return 0;
} }
...@@ -308,6 +308,8 @@ nouveau_therm_preinit(struct nouveau_therm *therm) ...@@ -308,6 +308,8 @@ nouveau_therm_preinit(struct nouveau_therm *therm)
nouveau_therm_ic_ctor(therm); nouveau_therm_ic_ctor(therm);
nouveau_therm_sensor_ctor(therm); nouveau_therm_sensor_ctor(therm);
nouveau_therm_fan_ctor(therm); nouveau_therm_fan_ctor(therm);
nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE);
return 0; return 0;
} }
......
...@@ -47,10 +47,17 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) ...@@ -47,10 +47,17 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
target = fan->percent; target = fan->percent;
target = max_t(u8, target, fan->bios.min_duty); target = max_t(u8, target, fan->bios.min_duty);
target = min_t(u8, target, fan->bios.max_duty); target = min_t(u8, target, fan->bios.max_duty);
if (fan->percent != target) {
nv_debug(therm, "FAN target: %d\n", target);
fan->percent = target; fan->percent = target;
}
/* smooth out the fanspeed increase/decrease */ /* check that we're not already at the target duty cycle */
duty = fan->get(therm); duty = fan->get(therm);
if (duty == target)
goto done;
/* smooth out the fanspeed increase/decrease */
if (!immediate && duty >= 0) { if (!immediate && duty >= 0) {
/* the constant "3" is a rough approximation taken from /* the constant "3" is a rough approximation taken from
* nvidia's behaviour. * nvidia's behaviour.
...@@ -64,6 +71,7 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) ...@@ -64,6 +71,7 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
duty = target; duty = target;
} }
nv_debug(therm, "FAN update: %d\n", duty);
ret = fan->set(therm, duty); ret = fan->set(therm, duty);
if (ret) if (ret)
goto done; goto done;
...@@ -161,7 +169,7 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) ...@@ -161,7 +169,7 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent)
{ {
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
if (priv->mode != FAN_CONTROL_MANUAL) if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL)
return -EINVAL; return -EINVAL;
return nouveau_therm_fan_set(therm, true, percent); return nouveau_therm_fan_set(therm, true, percent);
......
...@@ -76,6 +76,7 @@ struct nouveau_therm_priv { ...@@ -76,6 +76,7 @@ struct nouveau_therm_priv {
spinlock_t lock; spinlock_t lock;
struct nouveau_therm_trip_point *last_trip; struct nouveau_therm_trip_point *last_trip;
int mode; int mode;
int suspend;
/* bios */ /* bios */
struct nvbios_therm_sensor bios_sensor; struct nvbios_therm_sensor bios_sensor;
......
...@@ -108,7 +108,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, ...@@ -108,7 +108,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
switch (thrs) { switch (thrs) {
case NOUVEAU_THERM_THRS_FANBOOST: case NOUVEAU_THERM_THRS_FANBOOST:
nouveau_therm_fan_set(therm, true, 100); nouveau_therm_fan_set(therm, true, 100);
nouveau_therm_mode(therm, FAN_CONTROL_AUTO); nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
break; break;
case NOUVEAU_THERM_THRS_DOWNCLOCK: case NOUVEAU_THERM_THRS_DOWNCLOCK:
if (priv->emergency.downclock) if (priv->emergency.downclock)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment