Commit 63a02ce1 authored by Larry Finger's avatar Larry Finger Committed by David S. Miller

b43: Fix lockdep splat on module unload

On unload, b43 produces a lockdep warning that can be summarized in the
following way:

 ======================================================
 [ INFO: possible circular locking dependency detected ]
 3.8.0-wl+ #117 Not tainted
 -------------------------------------------------------
 modprobe/5557 is trying to acquire lock:
  ((&wl->firmware_load)){+.+.+.}, at: [<ffffffff81062160>] flush_work+0x0/0x2a0

 but task is already holding lock:
  (rtnl_mutex){+.+.+.}, at: [<ffffffff813bd7d2>] rtnl_lock+0x12/0x20

 which lock already depends on the new lock.
 [ INFO: possible circular locking dependency detected ]
 ======================================================

The full output is available at http://lkml.indiana.edu/hypermail/linux/kernel/1302.3/00060.html.
To summarize, commit 6b6fa586 added a 'cancel_work_sync(&wl->firmware_load)'
call in the wrong place.

The fix is to move the cancel_work_sync() call to b43_bcma_remove() and
b43_ssb_remove(). Thanks to Johannes Berg and Michael Buesch for help in
diagnosing the log output.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org> [V3.5+]
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7992ae6d
...@@ -4214,7 +4214,6 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) ...@@ -4214,7 +4214,6 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work); cancel_delayed_work_sync(&dev->periodic_work);
cancel_work_sync(&wl->tx_work); cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->firmware_load);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
dev = wl->current_dev; dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) { if (!dev || b43_status(dev) < B43_STAT_STARTED) {
...@@ -5434,6 +5433,7 @@ static void b43_bcma_remove(struct bcma_device *core) ...@@ -5434,6 +5433,7 @@ static void b43_bcma_remove(struct bcma_device *core)
/* We must cancel any work here before unregistering from ieee80211, /* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */ * as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
cancel_work_sync(&wl->firmware_load);
B43_WARN_ON(!wl); B43_WARN_ON(!wl);
if (!wldev->fw.ucode.data) if (!wldev->fw.ucode.data)
...@@ -5510,6 +5510,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) ...@@ -5510,6 +5510,7 @@ static void b43_ssb_remove(struct ssb_device *sdev)
/* We must cancel any work here before unregistering from ieee80211, /* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */ * as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
cancel_work_sync(&wl->firmware_load);
B43_WARN_ON(!wl); B43_WARN_ON(!wl);
if (!wldev->fw.ucode.data) if (!wldev->fw.ucode.data)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment