aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-12-18 03:43:33 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-19 07:33:33 -0500
commit34a3740d6b392896b71e36cd5cd68837a8f94a5c (patch)
tree128f9a3e35af1e7fc768b55fc7173cac9e1a3b08 /net/mac80211/util.c
parent6924d0138acdf5026ee4463134d98e139fe025a2 (diff)
mac80211: fix iflist_mtx/mtx locking in radar detection
The scan code creates an iflist_mtx -> mtx locking dependency, and a few other places, notably radar detection, were creating the opposite dependency, causing lockdep to complain. As scan and radar detection are mutually exclusive, the deadlock can't really happen in practice, but it's still bad form. A similar issue exists in the monitor mode code, but this is only used by channel-context drivers right now and those have to have hardware scan, so that also can't happen. Still, fix these issues by making some of the channel context code require the mtx to be held rather than acquiring it, thus allowing the monitor/radar callers to keep the iflist_mtx->mtx lock ordering. While at it, also fix access to the local->scanning variable in the radar code, and document that radar_detect_enabled is now properly protected by the mtx. All this would now introduce an ABBA deadlock between the DFS work cancelling and local->mtx, so change the locking there a bit to not need to use cancel_delayed_work_sync() but be able to just use cancel_delayed_work(). The work is also safely stopped/removed when the interface is stopped, so no extra changes are needed. Reported-by: Kalle Valo <kvalo@qca.qualcomm.com> Tested-by: Simon Wunderlich <sw@simonwunderlich.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 656648b9b9d3..ed93504d24b8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2315,9 +2315,14 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2315 struct ieee80211_sub_if_data *sdata; 2315 struct ieee80211_sub_if_data *sdata;
2316 struct cfg80211_chan_def chandef; 2316 struct cfg80211_chan_def chandef;
2317 2317
2318 mutex_lock(&local->mtx);
2318 mutex_lock(&local->iflist_mtx); 2319 mutex_lock(&local->iflist_mtx);
2319 list_for_each_entry(sdata, &local->interfaces, list) { 2320 list_for_each_entry(sdata, &local->interfaces, list) {
2320 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); 2321 /* it might be waiting for the local->mtx, but then
2322 * by the time it gets it, sdata->wdev.cac_started
2323 * will no longer be true
2324 */
2325 cancel_delayed_work(&sdata->dfs_cac_timer_work);
2321 2326
2322 if (sdata->wdev.cac_started) { 2327 if (sdata->wdev.cac_started) {
2323 chandef = sdata->vif.bss_conf.chandef; 2328 chandef = sdata->vif.bss_conf.chandef;
@@ -2329,6 +2334,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2329 } 2334 }
2330 } 2335 }
2331 mutex_unlock(&local->iflist_mtx); 2336 mutex_unlock(&local->iflist_mtx);
2337 mutex_unlock(&local->mtx);
2332} 2338}
2333 2339
2334void ieee80211_dfs_radar_detected_work(struct work_struct *work) 2340void ieee80211_dfs_radar_detected_work(struct work_struct *work)