Commit 3eac4abaa69949af0e2f64e5c55ee8a22bbdd3e7

Authored by Kevin Hilman
Committed by Linus Torvalds
1 parent 04287f975e

rwsem generic spinlock: use IRQ save/restore spinlocks

rwsems can be used with IRQs disabled, particularily in early boot
before IRQs are enabled.  Currently the spin_unlock_irq() usage in the
slow-patch will unconditionally enable interrupts and cause problems
since interrupts are not yet initialized or enabled.

This patch uses save/restore versions of IRQ spinlocks in the slowpath
to ensure interrupts are not unintentionally disabled.

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

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

lib/rwsem-spinlock.c
... ... @@ -143,13 +143,14 @@
143 143 {
144 144 struct rwsem_waiter waiter;
145 145 struct task_struct *tsk;
  146 + unsigned long flags;
146 147  
147   - spin_lock_irq(&sem->wait_lock);
  148 + spin_lock_irqsave(&sem->wait_lock, flags);
148 149  
149 150 if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
150 151 /* granted */
151 152 sem->activity++;
152   - spin_unlock_irq(&sem->wait_lock);
  153 + spin_unlock_irqrestore(&sem->wait_lock, flags);
153 154 goto out;
154 155 }
155 156  
... ... @@ -164,7 +165,7 @@
164 165 list_add_tail(&waiter.list, &sem->wait_list);
165 166  
166 167 /* we don't need to touch the semaphore struct anymore */
167   - spin_unlock_irq(&sem->wait_lock);
  168 + spin_unlock_irqrestore(&sem->wait_lock, flags);
168 169  
169 170 /* wait to be given the lock */
170 171 for (;;) {
171 172  
172 173  
... ... @@ -209,13 +210,14 @@
209 210 {
210 211 struct rwsem_waiter waiter;
211 212 struct task_struct *tsk;
  213 + unsigned long flags;
212 214  
213   - spin_lock_irq(&sem->wait_lock);
  215 + spin_lock_irqsave(&sem->wait_lock, flags);
214 216  
215 217 if (sem->activity == 0 && list_empty(&sem->wait_list)) {
216 218 /* granted */
217 219 sem->activity = -1;
218   - spin_unlock_irq(&sem->wait_lock);
  220 + spin_unlock_irqrestore(&sem->wait_lock, flags);
219 221 goto out;
220 222 }
221 223  
... ... @@ -230,7 +232,7 @@
230 232 list_add_tail(&waiter.list, &sem->wait_list);
231 233  
232 234 /* we don't need to touch the semaphore struct anymore */
233   - spin_unlock_irq(&sem->wait_lock);
  235 + spin_unlock_irqrestore(&sem->wait_lock, flags);
234 236  
235 237 /* wait to be given the lock */
236 238 for (;;) {