Commit 4a199068 authored by Johannes Berg's avatar Johannes Berg

mac80211: disentangle iflist_mtx and chanctx_mtx

At least on iwlwifi, sometimes lockdep complains that we can
lock
 chanctx_mtx -> mvm.mutex -> iflist_mtx
 (due to iterate_interfaces)
and
 iflist_mtx -> chanctx_mtx

Remove the latter dependency in mac80211 by using the RTNL
that we already hold in one case, and can relatively easily
achieve in the other case.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent cf147085
...@@ -739,11 +739,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, ...@@ -739,11 +739,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
return 0; return 0;
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
mutex_lock(&local->iflist_mtx);
if (local->use_chanctx) { if (local->use_chanctx) {
sdata = rcu_dereference_protected( sdata = rtnl_dereference(local->monitor_sdata);
local->monitor_sdata,
lockdep_is_held(&local->iflist_mtx));
if (sdata) { if (sdata) {
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
ret = ieee80211_vif_use_channel(sdata, chandef, ret = ieee80211_vif_use_channel(sdata, chandef,
...@@ -756,7 +753,6 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, ...@@ -756,7 +753,6 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
if (ret == 0) if (ret == 0)
local->monitor_chandef = *chandef; local->monitor_chandef = *chandef;
mutex_unlock(&local->iflist_mtx);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
return ret; return ret;
......
...@@ -253,6 +253,7 @@ static void ieee80211_restart_work(struct work_struct *work) ...@@ -253,6 +253,7 @@ static void ieee80211_restart_work(struct work_struct *work)
WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
"%s called with hardware scan in progress\n", __func__); "%s called with hardware scan in progress\n", __func__);
flush_work(&local->radar_detected_work);
rtnl_lock(); rtnl_lock();
list_for_each_entry(sdata, &local->interfaces, list) list_for_each_entry(sdata, &local->interfaces, list)
flush_delayed_work(&sdata->dec_tailroom_needed_wk); flush_delayed_work(&sdata->dec_tailroom_needed_wk);
...@@ -1187,6 +1188,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) ...@@ -1187,6 +1188,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
cancel_work_sync(&local->reconfig_filter); cancel_work_sync(&local->reconfig_filter);
cancel_work_sync(&local->tdls_chsw_work); cancel_work_sync(&local->tdls_chsw_work);
flush_work(&local->sched_scan_stopped_work); flush_work(&local->sched_scan_stopped_work);
flush_work(&local->radar_detected_work);
ieee80211_clear_tx_pending(local); ieee80211_clear_tx_pending(local);
rate_control_deinitialize(local); rate_control_deinitialize(local);
......
...@@ -2791,8 +2791,10 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) ...@@ -2791,8 +2791,10 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
/* for interface list, to avoid linking iflist_mtx and chanctx_mtx */
ASSERT_RTNL();
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
/* it might be waiting for the local->mtx, but then /* it might be waiting for the local->mtx, but then
* by the time it gets it, sdata->wdev.cac_started * by the time it gets it, sdata->wdev.cac_started
...@@ -2809,7 +2811,6 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) ...@@ -2809,7 +2811,6 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
GFP_KERNEL); GFP_KERNEL);
} }
} }
mutex_unlock(&local->iflist_mtx);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
} }
...@@ -2831,7 +2832,9 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work) ...@@ -2831,7 +2832,9 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
} }
mutex_unlock(&local->chanctx_mtx); mutex_unlock(&local->chanctx_mtx);
rtnl_lock();
ieee80211_dfs_cac_cancel(local); ieee80211_dfs_cac_cancel(local);
rtnl_unlock();
if (num_chanctx > 1) if (num_chanctx > 1)
/* XXX: multi-channel is not supported yet */ /* XXX: multi-channel is not supported yet */
...@@ -2846,7 +2849,7 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw) ...@@ -2846,7 +2849,7 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)
trace_api_radar_detected(local); trace_api_radar_detected(local);
ieee80211_queue_work(hw, &local->radar_detected_work); schedule_work(&local->radar_detected_work);
} }
EXPORT_SYMBOL(ieee80211_radar_detected); EXPORT_SYMBOL(ieee80211_radar_detected);
......
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