aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-12-05 19:28:34 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:00:25 -0500
commit1a22274b28fd47514f1463051d93028ad5f54af6 (patch)
tree392dc4690c146e0fbc729c26bf10852226e7aef9
parent041d62469f1efff280bbb9b2239e4e246da6e0d1 (diff)
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>
-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 7c83eccadc61..6b17b614629f 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 @@
4#include <core/device.h> 4#include <core/device.h>
5#include <core/subdev.h> 5#include <core/subdev.h>
6 6
7enum nouveau_therm_fan_mode { 7enum nouveau_therm_mode {
8 FAN_CONTROL_NONE = 0, 8 NOUVEAU_THERM_CTRL_NONE = 0,
9 FAN_CONTROL_MANUAL = 1, 9 NOUVEAU_THERM_CTRL_MANUAL = 1,
10 FAN_CONTROL_AUTO = 2, 10 NOUVEAU_THERM_CTRL_AUTO = 2,
11 FAN_CONTROL_NR,
12}; 11};
13 12
14enum nouveau_therm_attr_type { 13enum 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 f54495a0907a..b35b4a249c5f 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)
93 priv->mode = mode; 93 priv->mode = mode;
94 94
95 switch (mode) { 95 switch (mode) {
96 case FAN_CONTROL_MANUAL: 96 case NOUVEAU_THERM_CTRL_MANUAL:
97 duty = priv->fan->percent; 97 duty = nouveau_therm_fan_get(therm);
98 if (duty < 0)
99 duty = 100;
98 break; 100 break;
99 case FAN_CONTROL_AUTO: 101 case NOUVEAU_THERM_CTRL_AUTO:
100 if (priv->fan->bios.nr_fan_trip) 102 if (priv->fan->bios.nr_fan_trip)
101 duty = nouveau_therm_update_trip(therm); 103 duty = nouveau_therm_update_trip(therm);
102 else 104 else
103 duty = nouveau_therm_update_linear(therm); 105 duty = nouveau_therm_update_linear(therm);
104 break; 106 break;
105 case FAN_CONTROL_NONE: 107 case NOUVEAU_THERM_CTRL_NONE:
106 default: 108 default:
107 goto done; 109 goto done;
108 } 110 }
109 111
110 nouveau_therm_fan_set(therm, (mode != FAN_CONTROL_AUTO), duty); 112 nv_debug(therm, "FAN target request: %d%%\n", duty);
113 nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty);
111 114
112done: 115done:
113 if (list_empty(&priv->alarm.head) && (mode == FAN_CONTROL_AUTO)) 116 if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO))
114 ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); 117 ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
115 spin_unlock_irqrestore(&priv->lock, flags); 118 spin_unlock_irqrestore(&priv->lock, flags);
116} 119}
@@ -127,28 +130,22 @@ int
127nouveau_therm_mode(struct nouveau_therm *therm, int mode) 130nouveau_therm_mode(struct nouveau_therm *therm, int mode)
128{ 131{
129 struct nouveau_therm_priv *priv = (void *)therm; 132 struct nouveau_therm_priv *priv = (void *)therm;
130 133 struct nouveau_device *device = nv_device(therm);
131 if (priv->mode == mode) 134 static const char *name[] = {
132 return 0; 135 "disabled",
136 "manual",
137 "automatic"
138 };
133 139
134 /* The default PDAEMON ucode interferes with fan management */ 140 /* The default PDAEMON ucode interferes with fan management */
135 if (nv_device(therm)->card_type >= NV_C0) 141 if ((mode >= ARRAY_SIZE(name)) ||
142 (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
136 return -EINVAL; 143 return -EINVAL;
137 144
138 switch (mode) { 145 if (priv->mode == mode)
139 case FAN_CONTROL_NONE: 146 return 0;
140 nv_info(therm, "switch to no-control mode\n");
141 break;
142 case FAN_CONTROL_MANUAL:
143 nv_info(therm, "switch to manual mode\n");
144 break;
145 case FAN_CONTROL_AUTO:
146 nv_info(therm, "switch to automatic mode\n");
147 break;
148 default:
149 return -EINVAL;
150 }
151 147
148 nv_info(therm, "Thermal management: %s\n", name[mode]);
152 nouveau_therm_update(therm, mode); 149 nouveau_therm_update(therm, mode);
153 return 0; 150 return 0;
154} 151}
@@ -258,9 +255,8 @@ _nouveau_therm_init(struct nouveau_object *object)
258 if (ret) 255 if (ret)
259 return ret; 256 return ret;
260 257
261 if (priv->fan->percent >= 0) 258 if (priv->suspend >= 0)
262 therm->fan_set(therm, priv->fan->percent); 259 nouveau_therm_mode(therm, priv->mode);
263
264 priv->sensor.program_alarms(therm); 260 priv->sensor.program_alarms(therm);
265 return 0; 261 return 0;
266} 262}
@@ -271,7 +267,10 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend)
271 struct nouveau_therm *therm = (void *)object; 267 struct nouveau_therm *therm = (void *)object;
272 struct nouveau_therm_priv *priv = (void *)therm; 268 struct nouveau_therm_priv *priv = (void *)therm;
273 269
274 priv->fan->percent = therm->fan_get(therm); 270 if (suspend) {
271 priv->suspend = priv->mode;
272 priv->mode = NOUVEAU_THERM_CTRL_NONE;
273 }
275 274
276 return nouveau_subdev_fini(&therm->base, suspend); 275 return nouveau_subdev_fini(&therm->base, suspend);
277} 276}
@@ -299,6 +298,7 @@ nouveau_therm_create_(struct nouveau_object *parent,
299 priv->base.fan_sense = nouveau_therm_fan_sense; 298 priv->base.fan_sense = nouveau_therm_fan_sense;
300 priv->base.attr_get = nouveau_therm_attr_get; 299 priv->base.attr_get = nouveau_therm_attr_get;
301 priv->base.attr_set = nouveau_therm_attr_set; 300 priv->base.attr_set = nouveau_therm_attr_set;
301 priv->mode = priv->suspend = -1; /* undefined */
302 return 0; 302 return 0;
303} 303}
304 304
@@ -308,6 +308,8 @@ nouveau_therm_preinit(struct nouveau_therm *therm)
308 nouveau_therm_ic_ctor(therm); 308 nouveau_therm_ic_ctor(therm);
309 nouveau_therm_sensor_ctor(therm); 309 nouveau_therm_sensor_ctor(therm);
310 nouveau_therm_fan_ctor(therm); 310 nouveau_therm_fan_ctor(therm);
311
312 nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE);
311 return 0; 313 return 0;
312} 314}
313 315
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 0f210f0155a8..f7d32f49f657 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)
47 target = fan->percent; 47 target = fan->percent;
48 target = max_t(u8, target, fan->bios.min_duty); 48 target = max_t(u8, target, fan->bios.min_duty);
49 target = min_t(u8, target, fan->bios.max_duty); 49 target = min_t(u8, target, fan->bios.max_duty);
50 fan->percent = target; 50 if (fan->percent != target) {
51 nv_debug(therm, "FAN target: %d\n", target);
52 fan->percent = target;
53 }
51 54
52 /* smooth out the fanspeed increase/decrease */ 55 /* check that we're not already at the target duty cycle */
53 duty = fan->get(therm); 56 duty = fan->get(therm);
57 if (duty == target)
58 goto done;
59
60 /* smooth out the fanspeed increase/decrease */
54 if (!immediate && duty >= 0) { 61 if (!immediate && duty >= 0) {
55 /* the constant "3" is a rough approximation taken from 62 /* the constant "3" is a rough approximation taken from
56 * nvidia's behaviour. 63 * nvidia's behaviour.
@@ -64,6 +71,7 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
64 duty = target; 71 duty = target;
65 } 72 }
66 73
74 nv_debug(therm, "FAN update: %d\n", duty);
67 ret = fan->set(therm, duty); 75 ret = fan->set(therm, duty);
68 if (ret) 76 if (ret)
69 goto done; 77 goto done;
@@ -161,7 +169,7 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent)
161{ 169{
162 struct nouveau_therm_priv *priv = (void *)therm; 170 struct nouveau_therm_priv *priv = (void *)therm;
163 171
164 if (priv->mode != FAN_CONTROL_MANUAL) 172 if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL)
165 return -EINVAL; 173 return -EINVAL;
166 174
167 return nouveau_therm_fan_set(therm, true, percent); 175 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 c2413e6aae25..06b98706b3fc 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 {
76 spinlock_t lock; 76 spinlock_t lock;
77 struct nouveau_therm_trip_point *last_trip; 77 struct nouveau_therm_trip_point *last_trip;
78 int mode; 78 int mode;
79 int suspend;
79 80
80 /* bios */ 81 /* bios */
81 struct nvbios_therm_sensor bios_sensor; 82 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 d80c572de04f..820e09706578 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,
108 switch (thrs) { 108 switch (thrs) {
109 case NOUVEAU_THERM_THRS_FANBOOST: 109 case NOUVEAU_THERM_THRS_FANBOOST:
110 nouveau_therm_fan_set(therm, true, 100); 110 nouveau_therm_fan_set(therm, true, 100);
111 nouveau_therm_mode(therm, FAN_CONTROL_AUTO); 111 nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
112 break; 112 break;
113 case NOUVEAU_THERM_THRS_DOWNCLOCK: 113 case NOUVEAU_THERM_THRS_DOWNCLOCK:
114 if (priv->emergency.downclock) 114 if (priv->emergency.downclock)