diff options
Diffstat (limited to 'drivers/net/wireless/b43legacy/main.c')
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 14a5eea2573e..3e612d0a13e8 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2378,8 +2378,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw, | |||
2378 | } else | 2378 | } else |
2379 | err = b43legacy_dma_tx(dev, skb, ctl); | 2379 | err = b43legacy_dma_tx(dev, skb, ctl); |
2380 | out: | 2380 | out: |
2381 | if (unlikely(err)) | 2381 | if (unlikely(err)) { |
2382 | return NETDEV_TX_BUSY; | 2382 | /* Drop the packet. */ |
2383 | dev_kfree_skb_any(skb); | ||
2384 | } | ||
2383 | return NETDEV_TX_OK; | 2385 | return NETDEV_TX_OK; |
2384 | } | 2386 | } |
2385 | 2387 | ||
@@ -3039,7 +3041,6 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) | |||
3039 | /* Locking: wl->mutex */ | 3041 | /* Locking: wl->mutex */ |
3040 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) | 3042 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) |
3041 | { | 3043 | { |
3042 | struct b43legacy_wl *wl = dev->wl; | ||
3043 | struct b43legacy_phy *phy = &dev->phy; | 3044 | struct b43legacy_phy *phy = &dev->phy; |
3044 | u32 macctl; | 3045 | u32 macctl; |
3045 | 3046 | ||
@@ -3054,12 +3055,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) | |||
3054 | macctl |= B43legacy_MACCTL_PSM_JMP0; | 3055 | macctl |= B43legacy_MACCTL_PSM_JMP0; |
3055 | b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); | 3056 | b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); |
3056 | 3057 | ||
3057 | mutex_unlock(&wl->mutex); | ||
3058 | /* Must unlock as it would otherwise deadlock. No races here. | ||
3059 | * Cancel possibly pending workqueues. */ | ||
3060 | cancel_work_sync(&dev->restart_work); | ||
3061 | mutex_lock(&wl->mutex); | ||
3062 | |||
3063 | b43legacy_leds_exit(dev); | 3058 | b43legacy_leds_exit(dev); |
3064 | b43legacy_rng_exit(dev->wl); | 3059 | b43legacy_rng_exit(dev->wl); |
3065 | b43legacy_pio_free(dev); | 3060 | b43legacy_pio_free(dev); |
@@ -3486,6 +3481,8 @@ static void b43legacy_chip_reset(struct work_struct *work) | |||
3486 | } | 3481 | } |
3487 | } | 3482 | } |
3488 | out: | 3483 | out: |
3484 | if (err) | ||
3485 | wl->current_dev = NULL; /* Failed to init the dev. */ | ||
3489 | mutex_unlock(&wl->mutex); | 3486 | mutex_unlock(&wl->mutex); |
3490 | if (err) | 3487 | if (err) |
3491 | b43legacyerr(wl, "Controller restart FAILED\n"); | 3488 | b43legacyerr(wl, "Controller restart FAILED\n"); |
@@ -3618,9 +3615,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev) | |||
3618 | struct b43legacy_wldev *wldev; | 3615 | struct b43legacy_wldev *wldev; |
3619 | struct b43legacy_wl *wl; | 3616 | struct b43legacy_wl *wl; |
3620 | 3617 | ||
3618 | /* Do not cancel ieee80211-workqueue based work here. | ||
3619 | * See comment in b43legacy_remove(). */ | ||
3620 | |||
3621 | wldev = ssb_get_drvdata(dev); | 3621 | wldev = ssb_get_drvdata(dev); |
3622 | wl = wldev->wl; | 3622 | wl = wldev->wl; |
3623 | cancel_work_sync(&wldev->restart_work); | ||
3624 | b43legacy_debugfs_remove_device(wldev); | 3623 | b43legacy_debugfs_remove_device(wldev); |
3625 | b43legacy_wireless_core_detach(wldev); | 3624 | b43legacy_wireless_core_detach(wldev); |
3626 | list_del(&wldev->list); | 3625 | list_del(&wldev->list); |
@@ -3789,6 +3788,10 @@ static void b43legacy_remove(struct ssb_device *dev) | |||
3789 | struct b43legacy_wl *wl = ssb_get_devtypedata(dev); | 3788 | struct b43legacy_wl *wl = ssb_get_devtypedata(dev); |
3790 | struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); | 3789 | struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); |
3791 | 3790 | ||
3791 | /* We must cancel any work here before unregistering from ieee80211, | ||
3792 | * as the ieee80211 unreg will destroy the workqueue. */ | ||
3793 | cancel_work_sync(&wldev->restart_work); | ||
3794 | |||
3792 | B43legacy_WARN_ON(!wl); | 3795 | B43legacy_WARN_ON(!wl); |
3793 | if (wl->current_dev == wldev) | 3796 | if (wl->current_dev == wldev) |
3794 | ieee80211_unregister_hw(wl->hw); | 3797 | ieee80211_unregister_hw(wl->hw); |