aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43legacy
diff options
context:
space:
mode:
authorStefano Brivio <stefano.brivio@polimi.it>2007-11-07 12:33:37 -0500
committerJeff Garzik <jeff@garzik.org>2007-11-10 04:25:13 -0500
commit440cb58a7aa979fabb02a38e55bfe93adde0f41c (patch)
tree3b7f4276bb0eece22ba23f1b1ce651d8c537807c /drivers/net/wireless/b43legacy
parenta19d12d742903c745890c1374d64092595571e40 (diff)
b43legacy: fix shared IRQ race condition
Fix an IRQ race condition in b43legacy. If we call b43legacy_wireless_core_stop(), it will set the status of the device to INITIALIZED and the IRQ handler won't care any longer about IRQs, thus the kernel will disable the IRQ if it's shared (unless we boot it with the 'irqpoll' option). So we must disable IRQs before changing the device status. Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43legacy')
-rw-r--r--drivers/net/wireless/b43legacy/main.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index f0e56dfc9ec..1ebb787ef9c 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
2781 2781
2782 if (b43legacy_status(dev) < B43legacy_STAT_STARTED) 2782 if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
2783 return; 2783 return;
2784
2785 /* Disable and sync interrupts. We must do this before than
2786 * setting the status to INITIALIZED, as the interrupt handler
2787 * won't care about IRQs then. */
2788 spin_lock_irqsave(&wl->irq_lock, flags);
2789 dev->irq_savedstate = b43legacy_interrupt_disable(dev,
2790 B43legacy_IRQ_ALL);
2791 b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
2792 spin_unlock_irqrestore(&wl->irq_lock, flags);
2793 b43legacy_synchronize_irq(dev);
2794
2784 b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); 2795 b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
2785 2796
2786 mutex_unlock(&wl->mutex); 2797 mutex_unlock(&wl->mutex);
@@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
2791 2802
2792 ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ 2803 ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
2793 2804
2794 /* Disable and sync interrupts. */
2795 spin_lock_irqsave(&wl->irq_lock, flags);
2796 dev->irq_savedstate = b43legacy_interrupt_disable(dev,
2797 B43legacy_IRQ_ALL);
2798 b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
2799 spin_unlock_irqrestore(&wl->irq_lock, flags);
2800 b43legacy_synchronize_irq(dev);
2801
2802 b43legacy_mac_suspend(dev); 2805 b43legacy_mac_suspend(dev);
2803 free_irq(dev->dev->irq, dev); 2806 free_irq(dev->dev->irq, dev);
2804 b43legacydbg(wl, "Wireless interface stopped\n"); 2807 b43legacydbg(wl, "Wireless interface stopped\n");