summaryrefslogtreecommitdiffstats
path: root/net/mac80211/chan.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-06-15 09:20:45 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-06-20 12:57:08 +0200
commitc71420db653aba30a234d1e4cf86dde376e604fa (patch)
tree1e29e5b76bc2b04a6a3e93f9b362f3380b60558b /net/mac80211/chan.c
parentwifi: mac80211: ethtool: use deflink for now (diff)
downloadlinux-c71420db653aba30a234d1e4cf86dde376e604fa.tar.xz
linux-c71420db653aba30a234d1e4cf86dde376e604fa.zip
wifi: mac80211: RCU-ify link STA pointers
We need to be able to access these in a race-free way under traffic while adding/removing them, so RCU-ify the pointers. This requires passing a link_sta to a lot of functions so we don't have to do the RCU handling everywhere. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/chan.c')
-rw-r--r--net/mac80211/chan.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 4f25660d0eeb..6853b563fb6c 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -207,16 +207,20 @@ ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
unsigned int link_id)
{
- enum ieee80211_sta_rx_bandwidth width =
- ieee80211_sta_cap_rx_bw(sta, link_id);
+ enum ieee80211_sta_rx_bandwidth width;
+ struct link_sta_info *link_sta;
+
+ link_sta = rcu_dereference(sta->link[link_id]);
/* no effect if this STA has no presence on this link */
- if (!sta->sta.link[link_id])
+ if (!link_sta)
return NL80211_CHAN_WIDTH_20_NOHT;
+ width = ieee80211_sta_cap_rx_bw(link_sta);
+
switch (width) {
case IEEE80211_STA_RX_BW_20:
- if (sta->sta.link[link_id]->ht_cap.ht_supported)
+ if (link_sta->pub->ht_cap.ht_supported)
return NL80211_CHAN_WIDTH_20;
else
return NL80211_CHAN_WIDTH_20_NOHT;
@@ -416,6 +420,7 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
struct ieee80211_bss_conf *link_conf =
sdata->vif.link_conf[link_id];
+ struct link_sta_info *link_sta;
if (!link_conf)
continue;
@@ -423,18 +428,22 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
continue;
- new_sta_bw = ieee80211_sta_cur_vht_bw(sta, link_id);
+ link_sta = rcu_dereference(sta->link[link_id]);
+ if (!link_sta)
+ continue;
+
+ new_sta_bw = ieee80211_sta_cur_vht_bw(link_sta);
/* nothing change */
- if (new_sta_bw == sta->sta.link[link_id]->bandwidth)
+ if (new_sta_bw == link_sta->pub->bandwidth)
continue;
/* vif changed to narrow BW and narrow BW for station wasn't
* requested or vise versa */
- if ((new_sta_bw < sta->sta.link[link_id]->bandwidth) == !narrowed)
+ if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
continue;
- sta->sta.link[link_id]->bandwidth = new_sta_bw;
+ link_sta->pub->bandwidth = new_sta_bw;
rate_control_rate_update(local, sband, sta, link_id,
IEEE80211_RC_BW_CHANGED);
}