summaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-06-17 22:36:37 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:14 +0200
commitd8675a63518c6148827838058feb7f18403faed1 (patch)
treefbdee52aa9f31da2b33ad5804cc4ea76a9a82a24 /net/mac80211/util.c
parentwifi: nl80211: hold wdev mutex for station APIs (diff)
downloadlinux-d8675a63518c6148827838058feb7f18403faed1.tar.xz
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/util.c')
-rw-r--r--net/mac80211/util.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 645f75b0f89f..3e29ef1f81ad 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1702,7 +1702,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
sdata->vif.type != NL80211_IFTYPE_NAN) {
sdata->vif.bss_conf.qos = enable_qos;
if (bss_notify)
- ieee80211_link_info_change_notify(sdata, 0,
+ ieee80211_link_info_change_notify(sdata,
+ &sdata->deflink,
BSS_CHANGED_QOS);
}
}
@@ -2259,7 +2260,7 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
static void ieee80211_assign_chanctx(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
- unsigned int link_id)
+ struct ieee80211_link_data *link)
{
struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *ctx;
@@ -2268,11 +2269,11 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
return;
mutex_lock(&local->chanctx_mtx);
- conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf,
+ conf = rcu_dereference_protected(link->conf->chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (conf) {
ctx = container_of(conf, struct ieee80211_chanctx, conf);
- drv_assign_vif_chanctx(local, sdata, link_id, ctx);
+ drv_assign_vif_chanctx(local, sdata, link->link_id, ctx);
}
mutex_unlock(&local->chanctx_mtx);
}
@@ -2478,7 +2479,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
sdata = wiphy_dereference(local->hw.wiphy,
local->monitor_sdata);
if (sdata && ieee80211_sdata_running(sdata))
- ieee80211_assign_chanctx(local, sdata, 0);
+ ieee80211_assign_chanctx(local, sdata, &sdata->deflink);
}
/* reconfigure hardware */
@@ -2488,16 +2489,23 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* Finally also reconfigure all the BSS information */
list_for_each_entry(sdata, &local->interfaces, list) {
- unsigned int link;
+ unsigned int link_id;
u32 changed;
if (!ieee80211_sdata_running(sdata))
continue;
- for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
- if (sdata->vif.link_conf[link])
+ sdata_lock(sdata);
+ for (link_id = 0;
+ link_id < ARRAY_SIZE(sdata->vif.link_conf);
+ link_id++) {
+ struct ieee80211_link_data *link;
+
+ link = sdata_dereference(sdata->link[link_id], sdata);
+ if (link)
ieee80211_assign_chanctx(local, sdata, link);
}
+ sdata_unlock(sdata);
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
@@ -2807,7 +2815,7 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata,
- unsigned int link_id)
+ struct ieee80211_link_data *link)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *chanctx_conf;
@@ -2815,7 +2823,7 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->chanctx_mtx);
- chanctx_conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf,
+ chanctx_conf = rcu_dereference_protected(link->conf->chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
/*
@@ -3984,7 +3992,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
if (sdata->wdev.cac_started) {
chandef = sdata->vif.bss_conf.chandef;
- ieee80211_link_release_channel(sdata->link[0]);
+ ieee80211_link_release_channel(&sdata->deflink);
cfg80211_cac_event(sdata->dev,
&chandef,
NL80211_RADAR_CAC_ABORTED,
@@ -4430,13 +4438,11 @@ static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
!list_empty(&ctx->assigned_links));
list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
- struct ieee80211_sub_if_data *sdata = link->sdata;
-
if (!link->radar_required)
continue;
radar_detect |=
- BIT(sdata->vif.link_conf[link->link_id]->chandef.width);
+ BIT(link->conf->chandef.width);
}
return radar_detect;