diff options
author | Johannes Berg <johannes.berg@intel.com> | 2022-06-17 22:36:37 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2022-07-15 11:43:14 +0200 |
commit | d8675a63518c6148827838058feb7f18403faed1 (patch) | |
tree | fbdee52aa9f31da2b33ad5804cc4ea76a9a82a24 /net/mac80211/offchannel.c | |
parent | 3d1cc7cdf2e848181398837fe158bf0850d29ee6 (diff) |
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.c | 15 |
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; |