diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-12-05 19:28:34 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-02-20 01:00:25 -0500 |
commit | 1a22274b28fd47514f1463051d93028ad5f54af6 (patch) | |
tree | 392dc4690c146e0fbc729c26bf10852226e7aef9 | |
parent | 041d62469f1efff280bbb9b2239e4e246da6e0d1 (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.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/base.c | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | 2 |
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 | ||
7 | enum nouveau_therm_fan_mode { | 7 | enum 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 | ||
14 | enum nouveau_therm_attr_type { | 13 | 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 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 | ||
112 | done: | 115 | done: |
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 | |||
127 | nouveau_therm_mode(struct nouveau_therm *therm, int mode) | 130 | nouveau_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) |