diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2011-08-06 15:13:48 +0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-08-09 23:52:08 +0400 |
commit | abc11994112bf7441519e35f51c29ff5de5b0d4d (patch) | |
tree | 88b11da5cdec1a7a10ff7a388d29b94902c69653 /drivers/net/wireless/rt2x00/rt2x00dev.c | |
parent | c3ccb3341ec05444c8374d1829edc5157fc94853 (diff) | |
download | linux-abc11994112bf7441519e35f51c29ff5de5b0d4d.tar.xz |
rt2x00: Fix PCI interrupt processing race on SMP systems
When toggle_irq is called for PCI devices to disable device interrupts
it used tasklet_disable to wait for a possibly running tasklet to finish.
However, on SMP systems the tasklet might still be scheduled on another CPU.
Instead, use tasklet_kill to ensure that all scheduled tasklets are finished
before returning from toggle_irq.
Furthermore, it was possible that a tasklet reenabled its interrupt even
though interrupts have been disabled already. Fix this by checking the
DEVICE_STATE_ENABLED_RADIO flag before reenabling single interrupts
during tasklet processing.
While at it also enable/kill the TBTT and PRETBTT tasklets in the
toggle_irq callback and only use tasklet_kill in stop_queue to wait
for a currently scheduled beacon update before returning.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 1 |
1 files changed, 0 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0955c941317f..92ff6a72a2bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -946,7 +946,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) tasklet_init(&rt2x00dev->taskletname, \ rt2x00dev->ops->lib->taskletname, \ (unsigned long)rt2x00dev); \ - tasklet_disable(&rt2x00dev->taskletname); \ } RT2X00_TASKLET_INIT(txstatus_tasklet); |