summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-12-06 10:28:34 +1000
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 16:00:25 +1000
commit1a22274b28fd47514f1463051d93028ad5f54af6 (patch)
tree392dc4690c146e0fbc729c26bf10852226e7aef9 /drivers
parent041d62469f1efff280bbb9b2239e4e246da6e0d1 (diff)
downloadlinux-3.10-1a22274b28fd47514f1463051d93028ad5f54af6.tar.gz
linux-3.10-1a22274b28fd47514f1463051d93028ad5f54af6.tar.bz2
linux-3.10-1a22274b28fd47514f1463051d93028ad5f54af6.zip
drm/nouveau/therm: better transitions and debug logging
Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Martin Peres <martin.peres@labri.fr>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c2
5 files changed, 46 insertions, 36 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
index 7c83eccadc6..6b17b614629 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
@@ -4,11 +4,10 @@
#include <core/device.h>
#include <core/subdev.h>
-enum nouveau_therm_fan_mode {
- FAN_CONTROL_NONE = 0,
- FAN_CONTROL_MANUAL = 1,
- FAN_CONTROL_AUTO = 2,
- FAN_CONTROL_NR,
+enum nouveau_therm_mode {
+ NOUVEAU_THERM_CTRL_NONE = 0,
+ NOUVEAU_THERM_CTRL_MANUAL = 1,
+ NOUVEAU_THERM_CTRL_AUTO = 2,
};
enum nouveau_therm_attr_type {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
index f54495a0907..b35b4a249c5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
@@ -93,24 +93,27 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
priv->mode = mode;
switch (mode) {
- case FAN_CONTROL_MANUAL:
- duty = priv->fan->percent;
+ case NOUVEAU_THERM_CTRL_MANUAL:
+ duty = nouveau_therm_fan_get(therm);
+ if (duty < 0)
+ duty = 100;
break;
- case FAN_CONTROL_AUTO:
+ case NOUVEAU_THERM_CTRL_AUTO:
if (priv->fan->bios.nr_fan_trip)
duty = nouveau_therm_update_trip(therm);
else
duty = nouveau_therm_update_linear(therm);
break;
- case FAN_CONTROL_NONE:
+ case NOUVEAU_THERM_CTRL_NONE:
default:
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:
- 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);
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -127,28 +130,22 @@ int
nouveau_therm_mode(struct nouveau_therm *therm, int mode)
{
struct nouveau_therm_priv *priv = (void *)therm;
-
- if (priv->mode == mode)
- return 0;
+ struct nouveau_device *device = nv_device(therm);
+ static const char *name[] = {
+ "disabled",
+ "manual",
+ "automatic"
+ };
/* 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;
- switch (mode) {
- case FAN_CONTROL_NONE:
- 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;
- }
+ if (priv->mode == mode)
+ return 0;
+ nv_info(therm, "Thermal management: %s\n", name[mode]);
nouveau_therm_update(therm, mode);
return 0;
}
@@ -258,9 +255,8 @@ _nouveau_therm_init(struct nouveau_object *object)
if (ret)
return ret;
- if (priv->fan->percent >= 0)
- therm->fan_set(therm, priv->fan->percent);
-
+ if (priv->suspend >= 0)
+ nouveau_therm_mode(therm, priv->mode);
priv->sensor.program_alarms(therm);
return 0;
}
@@ -271,7 +267,10 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend)
struct nouveau_therm *therm = (void *)object;
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);
}
@@ -299,6 +298,7 @@ nouveau_therm_create_(struct nouveau_object *parent,
priv->base.fan_sense = nouveau_therm_fan_sense;
priv->base.attr_get = nouveau_therm_attr_get;
priv->base.attr_set = nouveau_therm_attr_set;
+ priv->mode = priv->suspend = -1; /* undefined */
return 0;
}
@@ -308,6 +308,8 @@ nouveau_therm_preinit(struct nouveau_therm *therm)
nouveau_therm_ic_ctor(therm);
nouveau_therm_sensor_ctor(therm);
nouveau_therm_fan_ctor(therm);
+
+ nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 0f210f0155a..f7d32f49f65 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -47,10 +47,17 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
target = fan->percent;
target = max_t(u8, target, fan->bios.min_duty);
target = min_t(u8, target, fan->bios.max_duty);
- fan->percent = target;
+ if (fan->percent != target) {
+ nv_debug(therm, "FAN target: %d\n", 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);
+ if (duty == target)
+ goto done;
+
+ /* smooth out the fanspeed increase/decrease */
if (!immediate && duty >= 0) {
/* the constant "3" is a rough approximation taken from
* nvidia's behaviour.
@@ -64,6 +71,7 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
duty = target;
}
+ nv_debug(therm, "FAN update: %d\n", duty);
ret = fan->set(therm, duty);
if (ret)
goto done;
@@ -161,7 +169,7 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent)
{
struct nouveau_therm_priv *priv = (void *)therm;
- if (priv->mode != FAN_CONTROL_MANUAL)
+ if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL)
return -EINVAL;
return nouveau_therm_fan_set(therm, true, percent);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index c2413e6aae2..06b98706b3f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -76,6 +76,7 @@ struct nouveau_therm_priv {
spinlock_t lock;
struct nouveau_therm_trip_point *last_trip;
int mode;
+ int suspend;
/* bios */
struct nvbios_therm_sensor bios_sensor;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
index d80c572de04..820e0970657 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
@@ -108,7 +108,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
switch (thrs) {
case NOUVEAU_THERM_THRS_FANBOOST:
nouveau_therm_fan_set(therm, true, 100);
- nouveau_therm_mode(therm, FAN_CONTROL_AUTO);
+ nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
break;
case NOUVEAU_THERM_THRS_DOWNCLOCK:
if (priv->emergency.downclock)