diff options
Diffstat (limited to 'drivers/net/wireless/b43legacy/main.c')
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f706ca65f159..5f533b93ad5d 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3036,7 +3036,6 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) | |||
3036 | /* Locking: wl->mutex */ | 3036 | /* Locking: wl->mutex */ |
3037 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) | 3037 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) |
3038 | { | 3038 | { |
3039 | struct b43legacy_wl *wl = dev->wl; | ||
3040 | struct b43legacy_phy *phy = &dev->phy; | 3039 | struct b43legacy_phy *phy = &dev->phy; |
3041 | u32 macctl; | 3040 | u32 macctl; |
3042 | 3041 | ||
@@ -3051,12 +3050,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) | |||
3051 | macctl |= B43legacy_MACCTL_PSM_JMP0; | 3050 | macctl |= B43legacy_MACCTL_PSM_JMP0; |
3052 | b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); | 3051 | b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); |
3053 | 3052 | ||
3054 | mutex_unlock(&wl->mutex); | ||
3055 | /* Must unlock as it would otherwise deadlock. No races here. | ||
3056 | * Cancel possibly pending workqueues. */ | ||
3057 | cancel_work_sync(&dev->restart_work); | ||
3058 | mutex_lock(&wl->mutex); | ||
3059 | |||
3060 | b43legacy_leds_exit(dev); | 3053 | b43legacy_leds_exit(dev); |
3061 | b43legacy_rng_exit(dev->wl); | 3054 | b43legacy_rng_exit(dev->wl); |
3062 | b43legacy_pio_free(dev); | 3055 | b43legacy_pio_free(dev); |
@@ -3482,6 +3475,8 @@ static void b43legacy_chip_reset(struct work_struct *work) | |||
3482 | } | 3475 | } |
3483 | } | 3476 | } |
3484 | out: | 3477 | out: |
3478 | if (err) | ||
3479 | wl->current_dev = NULL; /* Failed to init the dev. */ | ||
3485 | mutex_unlock(&wl->mutex); | 3480 | mutex_unlock(&wl->mutex); |
3486 | if (err) | 3481 | if (err) |
3487 | b43legacyerr(wl, "Controller restart FAILED\n"); | 3482 | b43legacyerr(wl, "Controller restart FAILED\n"); |
@@ -3614,9 +3609,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev) | |||
3614 | struct b43legacy_wldev *wldev; | 3609 | struct b43legacy_wldev *wldev; |
3615 | struct b43legacy_wl *wl; | 3610 | struct b43legacy_wl *wl; |
3616 | 3611 | ||
3612 | /* Do not cancel ieee80211-workqueue based work here. | ||
3613 | * See comment in b43legacy_remove(). */ | ||
3614 | |||
3617 | wldev = ssb_get_drvdata(dev); | 3615 | wldev = ssb_get_drvdata(dev); |
3618 | wl = wldev->wl; | 3616 | wl = wldev->wl; |
3619 | cancel_work_sync(&wldev->restart_work); | ||
3620 | b43legacy_debugfs_remove_device(wldev); | 3617 | b43legacy_debugfs_remove_device(wldev); |
3621 | b43legacy_wireless_core_detach(wldev); | 3618 | b43legacy_wireless_core_detach(wldev); |
3622 | list_del(&wldev->list); | 3619 | list_del(&wldev->list); |
@@ -3784,6 +3781,10 @@ static void b43legacy_remove(struct ssb_device *dev) | |||
3784 | struct b43legacy_wl *wl = ssb_get_devtypedata(dev); | 3781 | struct b43legacy_wl *wl = ssb_get_devtypedata(dev); |
3785 | struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); | 3782 | struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); |
3786 | 3783 | ||
3784 | /* We must cancel any work here before unregistering from ieee80211, | ||
3785 | * as the ieee80211 unreg will destroy the workqueue. */ | ||
3786 | cancel_work_sync(&wldev->restart_work); | ||
3787 | |||
3787 | B43legacy_WARN_ON(!wl); | 3788 | B43legacy_WARN_ON(!wl); |
3788 | if (wl->current_dev == wldev) | 3789 | if (wl->current_dev == wldev) |
3789 | ieee80211_unregister_hw(wl->hw); | 3790 | ieee80211_unregister_hw(wl->hw); |