Martin Peres
2014-Mar-13 23:48 UTC
[Nouveau] [PATCH] pm/fan: drop the fan lock in fan_update() before rescheduling
From: Martin Peres <martin.peres at labri.fr> This should fix a deadlock that has been reported to us where fan_update() would hold the fan lock and try to grab the alarm_program_lock to reschedule an update. On an other CPU, the alarm_program_lock would have been taken before calling fan_update(), leading to a deadlock. Reported-by: Marcin Slusarz <marcin.slusarz at gmail.com> Signed-off-by: Martin Peres <martin.peres at free.fr> --- nvkm/subdev/therm/fan.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/nvkm/subdev/therm/fan.c b/nvkm/subdev/therm/fan.c index 95f6129..29d4c41 100644 --- a/nvkm/subdev/therm/fan.c +++ b/nvkm/subdev/therm/fan.c @@ -54,8 +54,10 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) /* check that we're not already at the target duty cycle */ duty = fan->get(therm); - if (duty == target) - goto done; + if (duty == target) { + spin_unlock_irqrestore(&fan->lock, flags); + return 0; + } /* smooth out the fanspeed increase/decrease */ if (!immediate && duty >= 0) { @@ -73,8 +75,15 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) nv_debug(therm, "FAN update: %d\n", duty); ret = fan->set(therm, duty); - if (ret) - goto done; + if (ret) { + spin_unlock_irqrestore(&fan->lock, flags); + return ret; + } + + /* fan speed updated, drop the fan lock before grabbing the + * alarm-scheduling lock and risking a deadlock + */ + spin_unlock_irqrestore(&fan->lock, flags); /* schedule next fan update, if not at target speed already */ if (list_empty(&fan->alarm.head) && target != duty) { @@ -92,8 +101,6 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm); } -done: - spin_unlock_irqrestore(&fan->lock, flags); return ret; } -- 1.9.0
Martin Peres
2014-Mar-18 13:36 UTC
[Nouveau] [PATCH] pm/fan: drop the fan lock in fan_update() before rescheduling
Le 14/03/2014 00:48, Martin Peres a ?crit :> From: Martin Peres <martin.peres at labri.fr> > > This should fix a deadlock that has been reported to us where fan_update() > would hold the fan lock and try to grab the alarm_program_lock to reschedule > an update. On an other CPU, the alarm_program_lock would have been taken > before calling fan_update(), leading to a deadlock. > > Reported-by: Marcin Slusarz <marcin.slusarz at gmail.com> > Signed-off-by: Martin Peres <martin.peres at free.fr>Tested-by: Timoth?e Ravier <tim at siosm.fr> Cc: <stable at vger.kernel.org> # 3.9+ This problem dates back to fa37e8dda2617d48fbc6b17dd6e986e7f4c2bc8b. It would seem it got released in 3.9.
Apparently Analagous Threads
- [PATCH 1/4] pm/fan: drop the fan lock in fan_update() before rescheduling
- nouveau_fan_update: possible circular locking dependency detected
- [PATCH 3/3] gm107/therm: add PWM fan support
- [Bug 65554] New: CPU lock with nouveau_fan_update
- [PATCH 1/3] bios/fan: add support for maxwell's fan management table