diff options
author | John Stultz <john.stultz@linaro.org> | 2012-09-05 18:22:13 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2012-09-06 13:41:59 -0400 |
commit | 0ddaf741afc797cbb032168133d4e682829b1b82 (patch) | |
tree | 7769718979a10648061ba1f29a4d91626eb98101 | |
parent | d9c9138ed3c55b1f1ebfc6a3af092ba7ca7640fc (diff) |
wakeup: Use irqsave/irqrestore for events_locktracking-linaro-android-3.6-llct-20120910.0tracking-linaro-android-3.6-llct-20120907.1tracking-linaro-android-3.6-llct-20120907.0
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.
Full bug report here:
https://bugs.launchpad.net/linaro-landing-team-arm/+bug/1037565
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Android Team <kernel-team@android.com>
Cc: Arve Hjønnevåg <arve@android.com>
Reported-and-debugged-by: Jon Medhurst (Tixy) <tixy@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
-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 cbb463b3a750..0e4b093947ee 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -127,6 +127,8 @@ EXPORT_SYMBOL_GPL(wakeup_source_destroy); */ void wakeup_source_add(struct wakeup_source *ws) { + unsigned long flags; + if (WARN_ON(!ws)) return; @@ -135,9 +137,9 @@ void wakeup_source_add(struct wakeup_source *ws) ws->active = false; ws->last_time = ktime_get(); - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); list_add_rcu(&ws->entry, &wakeup_sources); - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); } EXPORT_SYMBOL_GPL(wakeup_source_add); @@ -147,12 +149,14 @@ EXPORT_SYMBOL_GPL(wakeup_source_add); */ void wakeup_source_remove(struct wakeup_source *ws) { + unsigned long flags; + if (WARN_ON(!ws)) return; - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); list_del_rcu(&ws->entry); - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); synchronize_rcu(); } EXPORT_SYMBOL_GPL(wakeup_source_remove); @@ -723,15 +727,16 @@ bool pm_get_wakeup_count(unsigned int *count, bool block) bool pm_save_wakeup_count(unsigned int count) { unsigned int cnt, inpr; + unsigned long flags; events_check_enabled = false; - spin_lock_irq(&events_lock); + spin_lock_irqsave(&events_lock, flags); split_counters(&cnt, &inpr); if (cnt == count && inpr == 0) { saved_count = count; events_check_enabled = true; } - spin_unlock_irq(&events_lock); + spin_unlock_irqrestore(&events_lock, flags); return events_check_enabled; } |