diff options
author | Luciano Coelho <coelho@ti.com> | 2011-06-30 08:32:41 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-07-05 14:42:36 -0400 |
commit | c10841ca722a0bc960dc541c51582773f9a24f98 (patch) | |
tree | f1e5901db0a530cfd4008f718a908a86bddcb333 /net/wireless/core.h | |
parent | 37000b305bff81bb1ee2f7f37b1319b670a08f76 (diff) |
cfg80211: fix deadlock with rfkill/sched_scan by adding new mutex
There was a deadlock when rfkill-blocking a wireless interface,
because we were locking the rdev mutex on NETDEV_GOING_DOWN to stop
sched_scans that were eventually running. The rfkill block code was
already holding a mutex under rdev:
kernel: =======================================================
kernel: [ INFO: possible circular locking dependency detected ]
kernel: 3.0.0-rc1-00049-g1fa7b6a #57
kernel: -------------------------------------------------------
kernel: kworker/0:1/4525 is trying to acquire lock:
kernel: (&rdev->mtx){+.+.+.}, at: [<ffffffff8164c831>] cfg80211_netdev_notifier_call+0x131/0x5b0
kernel:
kernel: but task is already holding lock:
kernel: (&rdev->devlist_mtx){+.+.+.}, at: [<ffffffff8164dcef>] cfg80211_rfkill_set_block+0x4f/0xa0
kernel:
kernel: which lock already depends on the new lock.
To fix this, add a new mutex specifically for sched_scan, to protect
the sched_scan_req element in the rdev struct, instead of using the
global rdev mutex.
Reported-by: Duane Griffin <duaneg@dghda.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/core.h')
-rw-r--r-- | net/wireless/core.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3dce1f167eba..a570ff9214ec 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -65,6 +65,8 @@ struct cfg80211_registered_device { struct work_struct scan_done_wk; struct work_struct sched_scan_results_wk; + struct mutex sched_scan_mtx; + #ifdef CONFIG_NL80211_TESTMODE struct genl_info *testmode_info; #endif |