diff options
author | Vincent Guittot <vincent.guittot@linaro.org> | 2019-02-21 02:59:02 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-02-21 04:29:00 -0500 |
commit | 74fb44863084275b952f21ec6a024af0e2e75cb8 (patch) | |
tree | 6d5f00f222dba81808cdde588f2660ab8163810a | |
parent | a3b22b9f11d9fbc48b0291ea92259a5a810e9438 (diff) |
PM-runtime: Fix deadlock when canceling hrtimer
When rpm_resume() desactivates the autosuspend timer, it should only
try to cancel hrtimer but not wait for the handler to finish, because
both rpm_resume() and pm_suspend_timer_fn() take the power.lock.
A deadlock is possible as follows:
CPU0 CPU1
rpm_resume()
spin_lock_irqsave
pm_suspend_timer_fn()
spin_lock_irqsave
pm_runtime_deactivate_timer()
hrtimer_cancel()
It is sufficient to call hrtimer_try_to_cancel() from
pm_runtime_deactivate_timer(), because dev->power.timer_expires
reset to 0 by it, so use that function instead of hrtimer_cancel().
Fixes: 8234f6734c5d ("PM-runtime: Switch autosuspend over to using hrtimers")
Reported-by: Sunzhaosheng Sun(Zhaosheng) <sunzhaosheng@hisilicon.com>
Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/base/power/runtime.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 0ea2139c50d8..ccd296dbb95c 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -95,7 +95,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status) | |||
95 | static void pm_runtime_deactivate_timer(struct device *dev) | 95 | static void pm_runtime_deactivate_timer(struct device *dev) |
96 | { | 96 | { |
97 | if (dev->power.timer_expires > 0) { | 97 | if (dev->power.timer_expires > 0) { |
98 | hrtimer_cancel(&dev->power.suspend_timer); | 98 | hrtimer_try_to_cancel(&dev->power.suspend_timer); |
99 | dev->power.timer_expires = 0; | 99 | dev->power.timer_expires = 0; |
100 | } | 100 | } |
101 | } | 101 | } |