mirror of
https://github.com/torvalds/linux.git
synced 2026-06-25 15:42:07 +02:00
Calling cancel_delayed_work() from inside
spin_lock_irqsave, introduces a potential deadlock.
As explained by Johannes Berg <johannes@sipsolutions.net>
A - lock
T - timer
phase CPU 1 CPU 2
---------------------------------------------
some place that calls
cancel_timer_sync()
(which is the | code)
lock-irq(A)
| "lock-irq"(T)
| "unlock"(T)
| wait(T)
unlock(A)
timer softirq
"lock"(T)
run(T)
"unlock"(T)
irq handler
lock(A)
unlock(A)
Now all that again, interleaved, leading to deadlock:
lock-irq(A)
"lock"(T)
run(T)
IRQ during or maybe
before run(T) --> lock(A)
"lock-irq"(T)
wait(T)
We fix this by moving the call to cancel_delayed_work() into workqueue.
There are cases where the work may not actually be queued or running
at the time we are trying to cancel it, but cancel_delayed_work() is
able to deal with this.
Also cleanup iwl_set_mode related to this call. This function
(iwl_set_mode) is only called when bringing interface up and there will
thus not be any scanning done. No need to try to cancel scanning.
Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13224, which was also
reported at http://marc.info/?l=linux-wireless&m=124081921903223&w=2 .
Tested-by: Miles Lane <miles.lane@gmail.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Acked-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
||
|---|---|---|
| .. | ||
| ar9170 | ||
| ath5k | ||
| ath9k | ||
| b43 | ||
| b43legacy | ||
| hostap | ||
| ipw2x00 | ||
| iwlwifi | ||
| libertas | ||
| libertas_tf | ||
| orinoco | ||
| p54 | ||
| prism54 | ||
| rt2x00 | ||
| rtl818x | ||
| zd1211rw | ||
| adm8211.c | ||
| adm8211.h | ||
| airo_cs.c | ||
| airo.c | ||
| airo.h | ||
| arlan-main.c | ||
| arlan-proc.c | ||
| arlan.h | ||
| at76c50x-usb.c | ||
| at76c50x-usb.h | ||
| atmel_cs.c | ||
| atmel_pci.c | ||
| atmel.c | ||
| atmel.h | ||
| i82586.h | ||
| i82593.h | ||
| Kconfig | ||
| mac80211_hwsim.c | ||
| Makefile | ||
| mwl8k.c | ||
| netwave_cs.c | ||
| ray_cs.c | ||
| ray_cs.h | ||
| rayctl.h | ||
| rndis_wlan.c | ||
| strip.c | ||
| wavelan_cs.c | ||
| wavelan_cs.h | ||
| wavelan_cs.p.h | ||
| wavelan.c | ||
| wavelan.h | ||
| wavelan.p.h | ||
| wl3501_cs.c | ||
| wl3501.h | ||
| zd1201.c | ||
| zd1201.h | ||