aboutsummaryrefslogtreecommitdiffstats
path: root/patches.runtime_pm/0197-PM-Sleep-Fix-possible-infinite-loop-during-wakeup-so.patch
blob: caf02a3f31de11c4b0c85efc5b703fd60db45e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
From 93978bb39092e1f4118fc414f7b0f817858c30ec Mon Sep 17 00:00:00 2001
From: "Rafael J. Wysocki" <rjw@sisk.pl>
Date: Fri, 17 Feb 2012 23:39:20 +0100
Subject: PM / Sleep: Fix possible infinite loop during wakeup source
 destruction
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If wakeup_source_destroy() is called for an active wakeup source that
is never deactivated, it will spin forever.  To prevent that from
happening, make wakeup_source_destroy() call __pm_relax() for the
wakeup source object it is about to free instead of waiting until
it will be deactivated by someone else.  However, for this to work
it also needs to make sure that the timer function will not be
executed after the final __pm_relax(), so make it run
del_timer_sync() on the wakeup source's timer beforehand.

Additionally, update the kerneldoc comment to document the
requirement that __pm_stay_awake() and __pm_wakeup_event() must not
be run in parallel with wakeup_source_destroy().

Reported-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
(cherry picked from commit d94aff87826ee6aa43032f4c0263482913f4e2c8)

Signed-off-by: Simon Horman <horms@verge.net.au>
---
 drivers/base/power/wakeup.c |   15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 6e591a8..d279f46 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -74,22 +74,17 @@ EXPORT_SYMBOL_GPL(wakeup_source_create);
 /**
  * wakeup_source_destroy - Destroy a struct wakeup_source object.
  * @ws: Wakeup source to destroy.
+ *
+ * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never
+ * be run in parallel with this function for the same wakeup source object.
  */
 void wakeup_source_destroy(struct wakeup_source *ws)
 {
 	if (!ws)
 		return;
 
-	spin_lock_irq(&ws->lock);
-	while (ws->active) {
-		spin_unlock_irq(&ws->lock);
-
-		schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
-
-		spin_lock_irq(&ws->lock);
-	}
-	spin_unlock_irq(&ws->lock);
-
+	del_timer_sync(&ws->timer);
+	__pm_relax(ws);
 	kfree(ws->name);
 	kfree(ws);
 }
-- 
1.7.10.1.362.g242cab3