Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / b43legacy / main.c
index b05a507..5f533b9 100644 (file)
@@ -2358,8 +2358,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
 }
 
 static int b43legacy_op_tx(struct ieee80211_hw *hw,
-                          struct sk_buff *skb,
-                          struct ieee80211_tx_control *ctl)
+                          struct sk_buff *skb)
 {
        struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
        struct b43legacy_wldev *dev = wl->current_dev;
@@ -2373,10 +2372,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw,
        /* DMA-TX is done without a global lock. */
        if (b43legacy_using_pio(dev)) {
                spin_lock_irqsave(&wl->irq_lock, flags);
-               err = b43legacy_pio_tx(dev, skb, ctl);
+               err = b43legacy_pio_tx(dev, skb);
                spin_unlock_irqrestore(&wl->irq_lock, flags);
        } else
-               err = b43legacy_dma_tx(dev, skb, ctl);
+               err = b43legacy_dma_tx(dev, skb);
 out:
        if (unlikely(err))
                return NETDEV_TX_BUSY;
@@ -3037,7 +3036,6 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
 /* Locking: wl->mutex */
 static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
 {
-       struct b43legacy_wl *wl = dev->wl;
        struct b43legacy_phy *phy = &dev->phy;
        u32 macctl;
 
@@ -3052,12 +3050,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
        macctl |= B43legacy_MACCTL_PSM_JMP0;
        b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
-       mutex_unlock(&wl->mutex);
-       /* Must unlock as it would otherwise deadlock. No races here.
-        * Cancel possibly pending workqueues. */
-       cancel_work_sync(&dev->restart_work);
-       mutex_lock(&wl->mutex);
-
        b43legacy_leds_exit(dev);
        b43legacy_rng_exit(dev->wl);
        b43legacy_pio_free(dev);
@@ -3409,7 +3401,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
         * field, but that would probably require resizing and moving of data
         * within the beacon template. Simply request a new beacon and let
         * mac80211 do the hard work. */
-       beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
+       beacon = ieee80211_beacon_get(hw, wl->vif);
        if (unlikely(!beacon))
                return -ENOMEM;
        spin_lock_irqsave(&wl->irq_lock, flags);
@@ -3420,8 +3412,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
 }
 
 static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
-                                          struct sk_buff *beacon,
-                                          struct ieee80211_tx_control *ctl)
+                                          struct sk_buff *beacon)
 {
        struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
        unsigned long flags;
@@ -3484,6 +3475,8 @@ static void b43legacy_chip_reset(struct work_struct *work)
                }
        }
 out:
+       if (err)
+               wl->current_dev = NULL; /* Failed to init the dev. */
        mutex_unlock(&wl->mutex);
        if (err)
                b43legacyerr(wl, "Controller restart FAILED\n");
@@ -3616,9 +3609,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev)
        struct b43legacy_wldev *wldev;
        struct b43legacy_wl *wl;
 
+       /* Do not cancel ieee80211-workqueue based work here.
+        * See comment in b43legacy_remove(). */
+
        wldev = ssb_get_drvdata(dev);
        wl = wldev->wl;
-       cancel_work_sync(&wldev->restart_work);
        b43legacy_debugfs_remove_device(wldev);
        b43legacy_wireless_core_detach(wldev);
        list_del(&wldev->list);
@@ -3786,6 +3781,10 @@ static void b43legacy_remove(struct ssb_device *dev)
        struct b43legacy_wl *wl = ssb_get_devtypedata(dev);
        struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
 
+       /* We must cancel any work here before unregistering from ieee80211,
+        * as the ieee80211 unreg will destroy the workqueue. */
+       cancel_work_sync(&wldev->restart_work);
+
        B43legacy_WARN_ON(!wl);
        if (wl->current_dev == wldev)
                ieee80211_unregister_hw(wl->hw);