]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/b43legacy/main.c
b43legacy: fix shared IRQ race condition
[linux-2.6] / drivers / net / wireless / b43legacy / main.c
index f0e56dfc9ecf7520928e089d197907fd3fe1f527..1ebb787ef9cfd61f16f05772d8234a6424488431 100644 (file)
@@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
 
        if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
                return;
+
+       /* Disable and sync interrupts. We must do this before than
+        * setting the status to INITIALIZED, as the interrupt handler
+        * won't care about IRQs then. */
+       spin_lock_irqsave(&wl->irq_lock, flags);
+       dev->irq_savedstate = b43legacy_interrupt_disable(dev,
+                                                         B43legacy_IRQ_ALL);
+       b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
+       spin_unlock_irqrestore(&wl->irq_lock, flags);
+       b43legacy_synchronize_irq(dev);
+
        b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
 
        mutex_unlock(&wl->mutex);
@@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
 
        ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
 
-       /* Disable and sync interrupts. */
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       dev->irq_savedstate = b43legacy_interrupt_disable(dev,
-                                                         B43legacy_IRQ_ALL);
-       b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-       b43legacy_synchronize_irq(dev);
-
        b43legacy_mac_suspend(dev);
        free_irq(dev->dev->irq, dev);
        b43legacydbg(wl, "Wireless interface stopped\n");