diff options
author | John Stultz <john.stultz@linaro.org> | 2012-09-06 17:19:06 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-06 17:19:06 -0400 |
commit | 4955070974ecfa0b1ae9d2506f529460fd3a4b0b (patch) | |
tree | 7eaf09c1756fa1bf2534998a60b9543cc411d79d /drivers/base | |
parent | 5834ec3aea8a84b70efeb52ee91a8f8b1042cd2a (diff) |
PM / wakeup: Use irqsave/irqrestore for events_lock
Jon Medhurst (Tixy) recently noticed a problem with the
events_lock usage. One of the Android patches that uses
wakeup_sources calls wakeup_source_add() with irqs disabled.
However, the event_lock usage in wakeup_source_add() uses
spin_lock_irq()/spin_unlock_irq(), which reenables interrupts.
This results in lockdep warnings.
The fix is to use spin_lock_irqsave()/spin_lock_irqrestore()
instead for the events_lock.
References: https://bugs.launchpad.net/linaro-landing-team-arm/+bug/1037565
Reported-and-debugged-by: Jon Medhurst (Tixy) <tixy@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/power/wakeup.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 8a0a9ca6ad65..e6ee5e80e546 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -127,6 +127,8 @@ EXPORT_SYMBOL_GPL(wakeup_source_destroy); | |||
127 | */ | 127 | */ |
128 | void wakeup_source_add(struct wakeup_source *ws) | 128 | void wakeup_source_add(struct wakeup_source *ws) |
129 | { | 129 | { |
130 | unsigned long flags; | ||
131 | |||
130 | if (WARN_ON(!ws)) | 132 | if (WARN_ON(!ws)) |
131 | return; | 133 | return; |
132 | 134 | ||
@@ -135,9 +137,9 @@ void wakeup_source_add(struct wakeup_source *ws) | |||
135 | ws->active = false; | 137 | ws->active = false; |
136 | ws->last_time = ktime_get(); | 138 | ws->last_time = ktime_get(); |
137 | 139 | ||
138 | spin_lock_irq(&events_lock); | 140 | spin_lock_irqsave(&events_lock, flags); |
139 | list_add_rcu(&ws->entry, &wakeup_sources); | 141 | list_add_rcu(&ws->entry, &wakeup_sources); |
140 | spin_unlock_irq(&events_lock); | 142 | spin_unlock_irqrestore(&events_lock, flags); |
141 | } | 143 | } |
142 | EXPORT_SYMBOL_GPL(wakeup_source_add); | 144 | EXPORT_SYMBOL_GPL(wakeup_source_add); |
143 | 145 | ||
@@ -147,12 +149,14 @@ EXPORT_SYMBOL_GPL(wakeup_source_add); | |||
147 | */ | 149 | */ |
148 | void wakeup_source_remove(struct wakeup_source *ws) | 150 | void wakeup_source_remove(struct wakeup_source *ws) |
149 | { | 151 | { |
152 | unsigned long flags; | ||
153 | |||
150 | if (WARN_ON(!ws)) | 154 | if (WARN_ON(!ws)) |
151 | return; | 155 | return; |
152 | 156 | ||
153 | spin_lock_irq(&events_lock); | 157 | spin_lock_irqsave(&events_lock, flags); |
154 | list_del_rcu(&ws->entry); | 158 | list_del_rcu(&ws->entry); |
155 | spin_unlock_irq(&events_lock); | 159 | spin_unlock_irqrestore(&events_lock, flags); |
156 | synchronize_rcu(); | 160 | synchronize_rcu(); |
157 | } | 161 | } |
158 | EXPORT_SYMBOL_GPL(wakeup_source_remove); | 162 | EXPORT_SYMBOL_GPL(wakeup_source_remove); |
@@ -752,15 +756,16 @@ bool pm_get_wakeup_count(unsigned int *count, bool block) | |||
752 | bool pm_save_wakeup_count(unsigned int count) | 756 | bool pm_save_wakeup_count(unsigned int count) |
753 | { | 757 | { |
754 | unsigned int cnt, inpr; | 758 | unsigned int cnt, inpr; |
759 | unsigned long flags; | ||
755 | 760 | ||
756 | events_check_enabled = false; | 761 | events_check_enabled = false; |
757 | spin_lock_irq(&events_lock); | 762 | spin_lock_irqsave(&events_lock, flags); |
758 | split_counters(&cnt, &inpr); | 763 | split_counters(&cnt, &inpr); |
759 | if (cnt == count && inpr == 0) { | 764 | if (cnt == count && inpr == 0) { |
760 | saved_count = count; | 765 | saved_count = count; |
761 | events_check_enabled = true; | 766 | events_check_enabled = true; |
762 | } | 767 | } |
763 | spin_unlock_irq(&events_lock); | 768 | spin_unlock_irqrestore(&events_lock, flags); |
764 | return events_check_enabled; | 769 | return events_check_enabled; |
765 | } | 770 | } |
766 | 771 | ||