This correctly cancels all workqueues on shutdown. Signed-off-by: Michael Buesch <mb@xxxxxxxxx> Cc: Larry Finger <larry.finger.lwfinger.net> Index: wireless-dev-new/drivers/net/wireless/b43/main.c =================================================================== --- wireless-dev-new.orig/drivers/net/wireless/b43/main.c 2007-08-28 20:23:35.000000000 +0200 +++ wireless-dev-new/drivers/net/wireless/b43/main.c 2007-08-28 20:36:27.000000000 +0200 @@ -2474,11 +2474,6 @@ static void b43_periodic_work_handler(st mutex_unlock(&dev->wl->mutex); } -static void b43_periodic_tasks_delete(struct b43_wldev *dev) -{ - cancel_rearming_delayed_work(&dev->periodic_work); -} - static void b43_periodic_tasks_setup(struct b43_wldev *dev) { struct delayed_work *work = &dev->periodic_work; @@ -3055,9 +3050,9 @@ static void b43_wireless_core_stop(struc b43_set_status(dev, B43_STAT_INITIALIZED); mutex_unlock(&wl->mutex); - /* Must unlock as it would otherwise deadlock. No races here. */ - b43_periodic_tasks_delete(dev); - flush_workqueue(dev->wl->hw->workqueue); + /* Must unlock as it would otherwise deadlock. No races here. + * Cancel the possibly running self-rearming periodic work. */ + cancel_delayed_work_sync(&dev->periodic_work); mutex_lock(&wl->mutex); ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy. @@ -3322,13 +3317,22 @@ static void b43_imcfglo_timeouts_workaro } /* Shutdown a wireless core */ +/* Locking: wl->mutex */ static void b43_wireless_core_exit(struct b43_wldev *dev) { + struct b43_wl *wl = dev->wl; struct b43_phy *phy = &dev->phy; B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); if (b43_status(dev) != B43_STAT_INITIALIZED) return; + b43_set_status(dev, B43_STAT_UNINIT); + + 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); b43_rng_exit(dev->wl); b43_pio_free(dev); @@ -3342,7 +3346,6 @@ static void b43_wireless_core_exit(struc phy->lo_control = NULL; ssb_device_disable(dev->dev, 0); ssb_bus_may_powerdown(dev->dev->bus); - b43_set_status(dev, B43_STAT_UNINIT); } /* Initialize a wireless core */ @@ -4001,6 +4004,9 @@ static void b43_remove(struct ssb_device /* Perform a hardware reset. This can be called from any context. */ void b43_controller_restart(struct b43_wldev *dev, const char *reason) { + /* Must avoid requeueing, if we are in shutdown. */ + if (b43_status(dev) < B43_STAT_INITIALIZED) + return; b43info(dev->wl, "Controller RESET (%s) ...\n", reason); queue_work(dev->wl->hw->workqueue, &dev->restart_work); } - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html