Commit be0df01d authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: reduce iflist_mtx

We now hold the wiphy mutex everywhere that we use or
needed the iflist_mtx, so we don't need this mutex any
more in mac80211. However, drivers may also iterate,
and in some cases (e.g. mt76) do so from high-priority
contexts. Thus, keep the mutex around but remove its
usage in mac80211 apart from those driver-visible parts
that are still needed.

Most of this change was done automatically with spatch,
with the parts that are still needed as described above
reverted manually.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0cd8080e
...@@ -2980,6 +2980,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -2980,6 +2980,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
bool update_txp_type = false; bool update_txp_type = false;
bool has_monitor = false; bool has_monitor = false;
lockdep_assert_wiphy(local->hw.wiphy);
if (wdev) { if (wdev) {
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
...@@ -3027,7 +3029,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -3027,7 +3029,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
break; break;
} }
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
has_monitor = true; has_monitor = true;
...@@ -3043,7 +3044,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -3043,7 +3044,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
continue; continue;
ieee80211_recalc_txpower(sdata, update_txp_type); ieee80211_recalc_txpower(sdata, update_txp_type);
} }
mutex_unlock(&local->iflist_mtx);
if (has_monitor) { if (has_monitor) {
sdata = wiphy_dereference(local->hw.wiphy, sdata = wiphy_dereference(local->hw.wiphy,
...@@ -4636,6 +4636,8 @@ static void ...@@ -4636,6 +4636,8 @@ static void
ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
u8 color, int enable, u64 changed) u8 color, int enable, u64 changed)
{ {
lockdep_assert_wiphy(sdata->local->hw.wiphy);
sdata->vif.bss_conf.he_bss_color.color = color; sdata->vif.bss_conf.he_bss_color.color = color;
sdata->vif.bss_conf.he_bss_color.enabled = enable; sdata->vif.bss_conf.he_bss_color.enabled = enable;
changed |= BSS_CHANGED_HE_BSS_COLOR; changed |= BSS_CHANGED_HE_BSS_COLOR;
...@@ -4645,7 +4647,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, ...@@ -4645,7 +4647,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) { if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
struct ieee80211_sub_if_data *child; struct ieee80211_sub_if_data *child;
mutex_lock(&sdata->local->iflist_mtx);
list_for_each_entry(child, &sdata->local->interfaces, list) { list_for_each_entry(child, &sdata->local->interfaces, list) {
if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) { if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) {
child->vif.bss_conf.he_bss_color.color = color; child->vif.bss_conf.he_bss_color.color = color;
...@@ -4655,7 +4656,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, ...@@ -4655,7 +4656,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
BSS_CHANGED_HE_BSS_COLOR); BSS_CHANGED_HE_BSS_COLOR);
} }
} }
mutex_unlock(&sdata->local->iflist_mtx);
} }
} }
......
...@@ -1738,7 +1738,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) ...@@ -1738,7 +1738,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
mutex_lock(&local->iflist_mtx); lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
...@@ -1746,7 +1747,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) ...@@ -1746,7 +1747,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
continue; continue;
sdata->u.ibss.last_scan_completed = jiffies; sdata->u.ibss.last_scan_completed = jiffies;
} }
mutex_unlock(&local->iflist_mtx);
} }
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
......
...@@ -33,14 +33,13 @@ ...@@ -33,14 +33,13 @@
* The interface list in each struct ieee80211_local is protected * The interface list in each struct ieee80211_local is protected
* three-fold: * three-fold:
* *
* (1) modifications may only be done under the RTNL * (1) modifications may only be done under the RTNL *and* wiphy mutex
* (2) modifications and readers are protected against each other by * *and* iflist_mtx
* the iflist_mtx. * (2) modifications are done in an RCU manner so atomic readers
* (3) modifications are done in an RCU manner so atomic readers
* can traverse the list in RCU-safe blocks. * can traverse the list in RCU-safe blocks.
* *
* As a consequence, reads (traversals) of the list can be protected * As a consequence, reads (traversals) of the list can be protected
* by either the RTNL, the iflist_mtx or RCU. * by either the RTNL, the wiphy mutex, the iflist_mtx or RCU.
*/ */
static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work); static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work);
...@@ -160,6 +159,8 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, ...@@ -160,6 +159,8 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
u8 *m; u8 *m;
int ret = 0; int ret = 0;
lockdep_assert_wiphy(local->hw.wiphy);
if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
return 0; return 0;
...@@ -176,7 +177,6 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, ...@@ -176,7 +177,6 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
if (!check_dup) if (!check_dup)
return ret; return ret;
mutex_lock(&local->iflist_mtx);
list_for_each_entry(iter, &local->interfaces, list) { list_for_each_entry(iter, &local->interfaces, list) {
if (iter == sdata) if (iter == sdata)
continue; continue;
...@@ -195,7 +195,6 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, ...@@ -195,7 +195,6 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
break; break;
} }
} }
mutex_unlock(&local->iflist_mtx);
return ret; return ret;
} }
...@@ -1049,7 +1048,7 @@ void ieee80211_recalc_offload(struct ieee80211_local *local) ...@@ -1049,7 +1048,7 @@ void ieee80211_recalc_offload(struct ieee80211_local *local)
if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD)) if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD))
return; return;
mutex_lock(&local->iflist_mtx); lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
...@@ -1057,8 +1056,6 @@ void ieee80211_recalc_offload(struct ieee80211_local *local) ...@@ -1057,8 +1056,6 @@ void ieee80211_recalc_offload(struct ieee80211_local *local)
ieee80211_recalc_sdata_offload(sdata); ieee80211_recalc_sdata_offload(sdata);
} }
mutex_unlock(&local->iflist_mtx);
} }
void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
...@@ -1917,6 +1914,8 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, ...@@ -1917,6 +1914,8 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
u8 tmp_addr[ETH_ALEN]; u8 tmp_addr[ETH_ALEN];
int i; int i;
lockdep_assert_wiphy(local->hw.wiphy);
/* default ... something at least */ /* default ... something at least */
memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
...@@ -1924,8 +1923,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, ...@@ -1924,8 +1923,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
local->hw.wiphy->n_addresses <= 1) local->hw.wiphy->n_addresses <= 1)
return; return;
mutex_lock(&local->iflist_mtx);
switch (type) { switch (type) {
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
/* doesn't matter */ /* doesn't matter */
...@@ -1949,7 +1946,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, ...@@ -1949,7 +1946,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); memcpy(perm_addr, sdata->vif.addr, ETH_ALEN);
goto out_unlock; return;
} }
} }
fallthrough; fallthrough;
...@@ -2035,9 +2032,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, ...@@ -2035,9 +2032,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
break; break;
} }
out_unlock:
mutex_unlock(&local->iflist_mtx);
} }
int ieee80211_if_add(struct ieee80211_local *local, const char *name, int ieee80211_if_add(struct ieee80211_local *local, const char *name,
...@@ -2051,6 +2045,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ...@@ -2051,6 +2045,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
int ret, i; int ret, i;
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_wiphy(local->hw.wiphy);
if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) { if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) {
struct wireless_dev *wdev; struct wireless_dev *wdev;
...@@ -2217,6 +2212,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ...@@ -2217,6 +2212,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
{ {
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_wiphy(sdata->local->hw.wiphy);
mutex_lock(&sdata->local->iflist_mtx); mutex_lock(&sdata->local->iflist_mtx);
list_del_rcu(&sdata->list); list_del_rcu(&sdata->list);
......
...@@ -2799,6 +2799,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ...@@ -2799,6 +2799,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
u64 vif_changed = BSS_CHANGED_ASSOC; u64 vif_changed = BSS_CHANGED_ASSOC;
unsigned int link_id; unsigned int link_id;
lockdep_assert_wiphy(local->hw.wiphy);
sdata->u.mgd.associated = true; sdata->u.mgd.associated = true;
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
...@@ -2860,9 +2862,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ...@@ -2860,9 +2862,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
vif_changed | changed[0]); vif_changed | changed[0]);
} }
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local); ieee80211_recalc_ps(local);
mutex_unlock(&local->iflist_mtx);
/* leave this here to not change ordering in non-MLO cases */ /* leave this here to not change ordering in non-MLO cases */
if (!ieee80211_vif_is_mld(&sdata->vif)) if (!ieee80211_vif_is_mld(&sdata->vif))
...@@ -3069,9 +3069,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) ...@@ -3069,9 +3069,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
__ieee80211_stop_poll(sdata); __ieee80211_stop_poll(sdata);
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local); ieee80211_recalc_ps(local);
mutex_unlock(&local->iflist_mtx);
if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
return; return;
...@@ -3267,9 +3265,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, ...@@ -3267,9 +3265,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
if (already) if (already)
goto out; goto out;
mutex_lock(&sdata->local->iflist_mtx);
ieee80211_recalc_ps(sdata->local); ieee80211_recalc_ps(sdata->local);
mutex_unlock(&sdata->local->iflist_mtx);
ifmgd->probe_send_count = 0; ifmgd->probe_send_count = 0;
ieee80211_mgd_probe_ap_send(sdata); ieee80211_mgd_probe_ap_send(sdata);
...@@ -6094,9 +6090,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, ...@@ -6094,9 +6090,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
changed |= BSS_CHANGED_BEACON_INFO; changed |= BSS_CHANGED_BEACON_INFO;
link->u.mgd.have_beacon = true; link->u.mgd.have_beacon = true;
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local); ieee80211_recalc_ps(local);
mutex_unlock(&local->iflist_mtx);
ieee80211_recalc_ps_vif(sdata); ieee80211_recalc_ps_vif(sdata);
} }
......
...@@ -84,6 +84,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) ...@@ -84,6 +84,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
lockdep_assert_wiphy(local->hw.wiphy);
if (WARN_ON(local->use_chanctx)) if (WARN_ON(local->use_chanctx))
return; return;
...@@ -101,7 +103,6 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) ...@@ -101,7 +103,6 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
false); false);
ieee80211_flush_queues(local, NULL, false); ieee80211_flush_queues(local, NULL, false);
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
...@@ -127,17 +128,17 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) ...@@ -127,17 +128,17 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
sdata->u.mgd.associated) sdata->u.mgd.associated)
ieee80211_offchannel_ps_enable(sdata); ieee80211_offchannel_ps_enable(sdata);
} }
mutex_unlock(&local->iflist_mtx);
} }
void ieee80211_offchannel_return(struct ieee80211_local *local) void ieee80211_offchannel_return(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
lockdep_assert_wiphy(local->hw.wiphy);
if (WARN_ON(local->use_chanctx)) if (WARN_ON(local->use_chanctx))
return; return;
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
continue; continue;
...@@ -161,7 +162,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) ...@@ -161,7 +162,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
BSS_CHANGED_BEACON_ENABLED); BSS_CHANGED_BEACON_ENABLED);
} }
} }
mutex_unlock(&local->iflist_mtx);
ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
......
...@@ -555,20 +555,18 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) ...@@ -555,20 +555,18 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *sdata_iter; struct ieee80211_sub_if_data *sdata_iter;
lockdep_assert_wiphy(local->hw.wiphy);
if (!ieee80211_is_radar_required(local)) if (!ieee80211_is_radar_required(local))
return true; return true;
if (!regulatory_pre_cac_allowed(local->hw.wiphy)) if (!regulatory_pre_cac_allowed(local->hw.wiphy))
return false; return false;
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata_iter, &local->interfaces, list) { list_for_each_entry(sdata_iter, &local->interfaces, list) {
if (sdata_iter->wdev.cac_started) { if (sdata_iter->wdev.cac_started)
mutex_unlock(&local->iflist_mtx);
return false; return false;
}
} }
mutex_unlock(&local->iflist_mtx);
return true; return true;
} }
...@@ -860,12 +858,13 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, ...@@ -860,12 +858,13 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
enum mac80211_scan_state next_scan_state; enum mac80211_scan_state next_scan_state;
struct cfg80211_scan_request *scan_req; struct cfg80211_scan_request *scan_req;
lockdep_assert_wiphy(local->hw.wiphy);
/* /*
* check if at least one STA interface is associated, * check if at least one STA interface is associated,
* check if at least one STA interface has pending tx frames * check if at least one STA interface has pending tx frames
* and grab the lowest used beacon interval * and grab the lowest used beacon interval
*/ */
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
...@@ -881,7 +880,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, ...@@ -881,7 +880,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
} }
} }
} }
mutex_unlock(&local->iflist_mtx);
scan_req = rcu_dereference_protected(local->scan_req, scan_req = rcu_dereference_protected(local->scan_req,
lockdep_is_held(&local->hw.wiphy->mtx)); lockdep_is_held(&local->hw.wiphy->mtx));
......
...@@ -4322,7 +4322,6 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) ...@@ -4322,7 +4322,6 @@ 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 */
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
......
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