aboutsummaryrefslogtreecommitdiff
path: root/net/mac80211/offchannel.c
diff options
context:
space:
mode:
authorGravatar Johannes Berg <johannes.berg@intel.com> 2022-06-17 22:36:37 +0200
committerGravatar Johannes Berg <johannes.berg@intel.com> 2022-07-15 11:43:14 +0200
commitd8675a63518c6148827838058feb7f18403faed1 (patch)
treefbdee52aa9f31da2b33ad5804cc4ea76a9a82a24 /net/mac80211/offchannel.c
parentwifi: nl80211: hold wdev mutex for station APIs (diff)
downloadlinux-d8675a63518c6148827838058feb7f18403faed1.tar.gz
linux-d8675a63518c6148827838058feb7f18403faed1.tar.bz2
linux-d8675a63518c6148827838058feb7f18403faed1.zip
wifi: mac80211: RCU-ify link/link_conf pointers
Since links can be added and removed dynamically, we need to somehow protect the sdata->link[] and vif->link_conf[] array pointers from disappearing when accessing them without locks. RCU-ify the pointers to achieve this, which requires quite a bit of rework. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/offchannel.c')
-rw-r--r--net/mac80211/offchannel.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index aff5d3c39902..be79ae68754e 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -119,7 +119,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
&sdata->state);
sdata->vif.bss_conf.enable_beacon = false;
ieee80211_link_info_change_notify(
- sdata, 0, BSS_CHANGED_BEACON_ENABLED);
+ sdata, &sdata->deflink,
+ BSS_CHANGED_BEACON_ENABLED);
}
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
@@ -156,7 +157,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
&sdata->state)) {
sdata->vif.bss_conf.enable_beacon = true;
ieee80211_link_info_change_notify(
- sdata, 0, BSS_CHANGED_BEACON_ENABLED);
+ sdata, &sdata->deflink,
+ BSS_CHANGED_BEACON_ENABLED);
}
}
mutex_unlock(&local->iflist_mtx);
@@ -848,14 +850,17 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
rcu_read_lock();
/* Check all the links first */
for (i = 0; i < ARRAY_SIZE(sdata->vif.link_conf); i++) {
- if (!sdata->vif.link_conf[i])
+ struct ieee80211_bss_conf *conf;
+
+ conf = rcu_dereference(sdata->vif.link_conf[i]);
+ if (!conf)
continue;
- chanctx_conf = rcu_dereference(sdata->vif.link_conf[i]->chanctx_conf);
+ chanctx_conf = rcu_dereference(conf->chanctx_conf);
if (!chanctx_conf)
continue;
- if (ether_addr_equal(sdata->vif.link_conf[i]->addr, mgmt->sa))
+ if (ether_addr_equal(conf->addr, mgmt->sa))
break;
chanctx_conf = NULL;