Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -739,11 +739,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
		return 0;

	mutex_lock(&local->mtx);
	mutex_lock(&local->iflist_mtx);
	if (local->use_chanctx) {
		sdata = rcu_dereference_protected(
				local->monitor_sdata,
				lockdep_is_held(&local->iflist_mtx));
		sdata = rtnl_dereference(local->monitor_sdata);
		if (sdata) {
			ieee80211_vif_release_channel(sdata);
			ret = ieee80211_vif_use_channel(sdata, chandef,
@@ -756,7 +753,6 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,

	if (ret == 0)
		local->monitor_chandef = *chandef;
	mutex_unlock(&local->iflist_mtx);
	mutex_unlock(&local->mtx);

	return ret;
+2 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ static void ieee80211_restart_work(struct work_struct *work)
	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
	     "%s called with hardware scan in progress\n", __func__);

	flush_work(&local->radar_detected_work);
	rtnl_lock();
	list_for_each_entry(sdata, &local->interfaces, list)
		flush_delayed_work(&sdata->dec_tailroom_needed_wk);
@@ -1187,6 +1188,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
	cancel_work_sync(&local->reconfig_filter);
	cancel_work_sync(&local->tdls_chsw_work);
	flush_work(&local->sched_scan_stopped_work);
	flush_work(&local->radar_detected_work);

	ieee80211_clear_tx_pending(local);
	rate_control_deinitialize(local);
+6 −3
Original line number Diff line number Diff line
@@ -2791,8 +2791,10 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
	struct ieee80211_sub_if_data *sdata;
	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->iflist_mtx);
	list_for_each_entry(sdata, &local->interfaces, list) {
		/* it might be waiting for the local->mtx, but then
		 * by the time it gets it, sdata->wdev.cac_started
@@ -2809,7 +2811,6 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
					   GFP_KERNEL);
		}
	}
	mutex_unlock(&local->iflist_mtx);
	mutex_unlock(&local->mtx);
}

@@ -2831,7 +2832,9 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
	}
	mutex_unlock(&local->chanctx_mtx);

	rtnl_lock();
	ieee80211_dfs_cac_cancel(local);
	rtnl_unlock();

	if (num_chanctx > 1)
		/* XXX: multi-channel is not supported yet */
@@ -2846,7 +2849,7 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)

	trace_api_radar_detected(local);

	ieee80211_queue_work(hw, &local->radar_detected_work);
	schedule_work(&local->radar_detected_work);
}
EXPORT_SYMBOL(ieee80211_radar_detected);