Commit 4955070974ecfa0b1ae9d2506f529460fd3a4b0b

Authored by John Stultz
Committed by Rafael J. Wysocki
1 parent 5834ec3aea

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>

Showing 1 changed file with 11 additions and 6 deletions Side-by-side Diff

drivers/base/power/wakeup.c
... ... @@ -127,6 +127,8 @@
127 127 */
128 128 void wakeup_source_add(struct wakeup_source *ws)
129 129 {
  130 + unsigned long flags;
  131 +
130 132 if (WARN_ON(!ws))
131 133 return;
132 134  
133 135  
... ... @@ -135,9 +137,9 @@
135 137 ws->active = false;
136 138 ws->last_time = ktime_get();
137 139  
138   - spin_lock_irq(&events_lock);
  140 + spin_lock_irqsave(&events_lock, flags);
139 141 list_add_rcu(&ws->entry, &wakeup_sources);
140   - spin_unlock_irq(&events_lock);
  142 + spin_unlock_irqrestore(&events_lock, flags);
141 143 }
142 144 EXPORT_SYMBOL_GPL(wakeup_source_add);
143 145  
144 146  
145 147  
... ... @@ -147,12 +149,14 @@
147 149 */
148 150 void wakeup_source_remove(struct wakeup_source *ws)
149 151 {
  152 + unsigned long flags;
  153 +
150 154 if (WARN_ON(!ws))
151 155 return;
152 156  
153   - spin_lock_irq(&events_lock);
  157 + spin_lock_irqsave(&events_lock, flags);
154 158 list_del_rcu(&ws->entry);
155   - spin_unlock_irq(&events_lock);
  159 + spin_unlock_irqrestore(&events_lock, flags);
156 160 synchronize_rcu();
157 161 }
158 162 EXPORT_SYMBOL_GPL(wakeup_source_remove);
159 163  
160 164  
... ... @@ -752,15 +756,16 @@
752 756 bool pm_save_wakeup_count(unsigned int count)
753 757 {
754 758 unsigned int cnt, inpr;
  759 + unsigned long flags;
755 760  
756 761 events_check_enabled = false;
757   - spin_lock_irq(&events_lock);
  762 + spin_lock_irqsave(&events_lock, flags);
758 763 split_counters(&cnt, &inpr);
759 764 if (cnt == count && inpr == 0) {
760 765 saved_count = count;
761 766 events_check_enabled = true;
762 767 }
763   - spin_unlock_irq(&events_lock);
  768 + spin_unlock_irqrestore(&events_lock, flags);
764 769 return events_check_enabled;
765 770 }
766 771