aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2013-08-11 22:48:52 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-09-03 23:46:52 -0400
commitc4a62a766062c268d08c1aacf2e18e057e277db4 (patch)
tree381ecbe9bcdc9c009e359720a281b235c78e8760
parentb925a75d6729cec8debd0c378b354d8c228b36aa (diff)
drm/nouveau/therm: survive to suspend/resume cycles
Therm uses 3 ptimer alarms. Two to drive the fan and one for polling the temperature. When suspending/resuming, alarms will never be fired. As we are checking if there isn't an alarm pending before rescheduling another one, we end up never checking temperature or updating the fan speed. This commit also adds debug messages to be able to spot more easily if this case happens again in the future. Sorry for the spam if you activate the debug level though. Tested-by: Dash Four <mr.dash.four@googlemail.com> v2: - fix temperature polling too Signed-off-by: Martin Peres <martin.peres@labri.fr> Tested-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c17
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c21
4 files changed, 51 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
index 2ada3d71312f..f1de7a9c572b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
@@ -95,12 +95,14 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
95 int duty; 95 int duty;
96 96
97 spin_lock_irqsave(&priv->lock, flags); 97 spin_lock_irqsave(&priv->lock, flags);
98 nv_debug(therm, "FAN speed check\n");
98 if (mode < 0) 99 if (mode < 0)
99 mode = priv->mode; 100 mode = priv->mode;
100 priv->mode = mode; 101 priv->mode = mode;
101 102
102 switch (mode) { 103 switch (mode) {
103 case NOUVEAU_THERM_CTRL_MANUAL: 104 case NOUVEAU_THERM_CTRL_MANUAL:
105 ptimer->alarm_cancel(ptimer, &priv->alarm);
104 duty = nouveau_therm_fan_get(therm); 106 duty = nouveau_therm_fan_get(therm);
105 if (duty < 0) 107 if (duty < 0)
106 duty = 100; 108 duty = 100;
@@ -113,6 +115,7 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
113 break; 115 break;
114 case NOUVEAU_THERM_CTRL_NONE: 116 case NOUVEAU_THERM_CTRL_NONE:
115 default: 117 default:
118 ptimer->alarm_cancel(ptimer, &priv->alarm);
116 goto done; 119 goto done;
117 } 120 }
118 121
@@ -122,6 +125,8 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)
122done: 125done:
123 if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) 126 if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO))
124 ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); 127 ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
128 else if (!list_empty(&priv->alarm.head))
129 nv_debug(therm, "therm fan alarm list is not empty\n");
125 spin_unlock_irqrestore(&priv->lock, flags); 130 spin_unlock_irqrestore(&priv->lock, flags);
126} 131}
127 132
@@ -274,7 +279,8 @@ _nouveau_therm_init(struct nouveau_object *object)
274 279
275 nouveau_therm_fan_mode(therm, priv->suspend); 280 nouveau_therm_fan_mode(therm, priv->suspend);
276 } 281 }
277 priv->sensor.program_alarms(therm); 282 nouveau_therm_sensor_init(therm);
283 nouveau_therm_fan_init(therm);
278 return 0; 284 return 0;
279} 285}
280 286
@@ -284,6 +290,8 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend)
284 struct nouveau_therm *therm = (void *)object; 290 struct nouveau_therm *therm = (void *)object;
285 struct nouveau_therm_priv *priv = (void *)therm; 291 struct nouveau_therm_priv *priv = (void *)therm;
286 292
293 nouveau_therm_fan_fini(therm, suspend);
294 nouveau_therm_sensor_fini(therm, suspend);
287 if (suspend) { 295 if (suspend) {
288 priv->suspend = priv->mode; 296 priv->suspend = priv->mode;
289 priv->mode = NOUVEAU_THERM_CTRL_NONE; 297 priv->mode = NOUVEAU_THERM_CTRL_NONE;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 4d8450fcf0a0..39f47b950ad1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -204,6 +204,23 @@ nouveau_therm_fan_safety_checks(struct nouveau_therm *therm)
204} 204}
205 205
206int 206int
207nouveau_therm_fan_init(struct nouveau_therm *therm)
208{
209 return 0;
210}
211
212int
213nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend)
214{
215 struct nouveau_therm_priv *priv = (void *)therm;
216 struct nouveau_timer *ptimer = nouveau_timer(therm);
217
218 if (suspend)
219 ptimer->alarm_cancel(ptimer, &priv->fan->alarm);
220 return 0;
221}
222
223int
207nouveau_therm_fan_ctor(struct nouveau_therm *therm) 224nouveau_therm_fan_ctor(struct nouveau_therm *therm)
208{ 225{
209 struct nouveau_therm_priv *priv = (void *)therm; 226 struct nouveau_therm_priv *priv = (void *)therm;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 15ca64e481f1..dd38529262fb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -113,6 +113,8 @@ void nouveau_therm_ic_ctor(struct nouveau_therm *therm);
113int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); 113int nouveau_therm_sensor_ctor(struct nouveau_therm *therm);
114 114
115int nouveau_therm_fan_ctor(struct nouveau_therm *therm); 115int nouveau_therm_fan_ctor(struct nouveau_therm *therm);
116int nouveau_therm_fan_init(struct nouveau_therm *therm);
117int nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend);
116int nouveau_therm_fan_get(struct nouveau_therm *therm); 118int nouveau_therm_fan_get(struct nouveau_therm *therm);
117int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); 119int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent);
118int nouveau_therm_fan_user_get(struct nouveau_therm *therm); 120int nouveau_therm_fan_user_get(struct nouveau_therm *therm);
@@ -122,6 +124,8 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm);
122 124
123int nouveau_therm_preinit(struct nouveau_therm *); 125int nouveau_therm_preinit(struct nouveau_therm *);
124 126
127int nouveau_therm_sensor_init(struct nouveau_therm *therm);
128int nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend);
125void nouveau_therm_sensor_preinit(struct nouveau_therm *); 129void nouveau_therm_sensor_preinit(struct nouveau_therm *);
126void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, 130void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm,
127 enum nouveau_therm_thrs thrs, 131 enum nouveau_therm_thrs thrs,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
index dde746c78c8a..b80a33011b93 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
@@ -180,6 +180,8 @@ alarm_timer_callback(struct nouveau_alarm *alarm)
180 180
181 spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); 181 spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
182 182
183 nv_debug(therm, "polling the internal temperature\n");
184
183 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, 185 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost,
184 NOUVEAU_THERM_THRS_FANBOOST); 186 NOUVEAU_THERM_THRS_FANBOOST);
185 187
@@ -216,6 +218,25 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
216 alarm_timer_callback(&priv->sensor.therm_poll_alarm); 218 alarm_timer_callback(&priv->sensor.therm_poll_alarm);
217} 219}
218 220
221int
222nouveau_therm_sensor_init(struct nouveau_therm *therm)
223{
224 struct nouveau_therm_priv *priv = (void *)therm;
225 priv->sensor.program_alarms(therm);
226 return 0;
227}
228
229int
230nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend)
231{
232 struct nouveau_therm_priv *priv = (void *)therm;
233 struct nouveau_timer *ptimer = nouveau_timer(therm);
234
235 if (suspend)
236 ptimer->alarm_cancel(ptimer, &priv->sensor.therm_poll_alarm);
237 return 0;
238}
239
219void 240void
220nouveau_therm_sensor_preinit(struct nouveau_therm *therm) 241nouveau_therm_sensor_preinit(struct nouveau_therm *therm)
221{ 242{