aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.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/mlme.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/mlme.c')
-rw-r--r--net/mac80211/mlme.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9c2c7ee2cc30..fc1d82465b3c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -888,7 +888,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
888 if (!ifmgd->associated) 888 if (!ifmgd->associated)
889 goto out; 889 goto out;
890 890
891 mutex_lock(&local->mtx);
891 ret = ieee80211_vif_change_channel(sdata, &changed); 892 ret = ieee80211_vif_change_channel(sdata, &changed);
893 mutex_unlock(&local->mtx);
892 if (ret) { 894 if (ret) {
893 sdata_info(sdata, 895 sdata_info(sdata,
894 "vif channel switch failed, disconnecting\n"); 896 "vif channel switch failed, disconnecting\n");
@@ -1401,10 +1403,14 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
1401 dfs_cac_timer_work); 1403 dfs_cac_timer_work);
1402 struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; 1404 struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
1403 1405
1404 ieee80211_vif_release_channel(sdata); 1406 mutex_lock(&sdata->local->mtx);
1405 cfg80211_cac_event(sdata->dev, &chandef, 1407 if (sdata->wdev.cac_started) {
1406 NL80211_RADAR_CAC_FINISHED, 1408 ieee80211_vif_release_channel(sdata);
1407 GFP_KERNEL); 1409 cfg80211_cac_event(sdata->dev, &chandef,
1410 NL80211_RADAR_CAC_FINISHED,
1411 GFP_KERNEL);
1412 }
1413 mutex_unlock(&sdata->local->mtx);
1408} 1414}
1409 1415
1410/* MLME */ 1416/* MLME */
@@ -1747,7 +1753,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1747 ifmgd->have_beacon = false; 1753 ifmgd->have_beacon = false;
1748 1754
1749 ifmgd->flags = 0; 1755 ifmgd->flags = 0;
1756 mutex_lock(&local->mtx);
1750 ieee80211_vif_release_channel(sdata); 1757 ieee80211_vif_release_channel(sdata);
1758 mutex_unlock(&local->mtx);
1751 1759
1752 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; 1760 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1753} 1761}
@@ -2070,7 +2078,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
2070 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2078 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2071 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2079 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2072 sdata->u.mgd.flags = 0; 2080 sdata->u.mgd.flags = 0;
2081 mutex_lock(&sdata->local->mtx);
2073 ieee80211_vif_release_channel(sdata); 2082 ieee80211_vif_release_channel(sdata);
2083 mutex_unlock(&sdata->local->mtx);
2074 } 2084 }
2075 2085
2076 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); 2086 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
@@ -2319,7 +2329,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2319 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2329 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2320 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2330 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2321 sdata->u.mgd.flags = 0; 2331 sdata->u.mgd.flags = 0;
2332 mutex_lock(&sdata->local->mtx);
2322 ieee80211_vif_release_channel(sdata); 2333 ieee80211_vif_release_channel(sdata);
2334 mutex_unlock(&sdata->local->mtx);
2323 } 2335 }
2324 2336
2325 kfree(assoc_data); 2337 kfree(assoc_data);
@@ -3670,6 +3682,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3670 /* will change later if needed */ 3682 /* will change later if needed */
3671 sdata->smps_mode = IEEE80211_SMPS_OFF; 3683 sdata->smps_mode = IEEE80211_SMPS_OFF;
3672 3684
3685 mutex_lock(&local->mtx);
3673 /* 3686 /*
3674 * If this fails (possibly due to channel context sharing 3687 * If this fails (possibly due to channel context sharing
3675 * on incompatible channels, e.g. 80+80 and 160 sharing the 3688 * on incompatible channels, e.g. 80+80 and 160 sharing the
@@ -3681,13 +3694,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3681 /* don't downgrade for 5 and 10 MHz channels, though. */ 3694 /* don't downgrade for 5 and 10 MHz channels, though. */
3682 if (chandef.width == NL80211_CHAN_WIDTH_5 || 3695 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
3683 chandef.width == NL80211_CHAN_WIDTH_10) 3696 chandef.width == NL80211_CHAN_WIDTH_10)
3684 return ret; 3697 goto out;
3685 3698
3686 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3699 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
3687 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); 3700 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
3688 ret = ieee80211_vif_use_channel(sdata, &chandef, 3701 ret = ieee80211_vif_use_channel(sdata, &chandef,
3689 IEEE80211_CHANCTX_SHARED); 3702 IEEE80211_CHANCTX_SHARED);
3690 } 3703 }
3704 out:
3705 mutex_unlock(&local->mtx);
3691 return ret; 3706 return ret;
3692} 3707}
3693 3708