summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2023-06-19 16:26:49 +0300
committerJohannes Berg <johannes.berg@intel.com>2023-06-21 14:01:28 +0200
commit4484de23ba22e3023e9cbe4246a927ffb00db56f (patch)
tree914bf1159b72bf4c7c29a4449b4509b3a81bf7b4
parent5c1f97537bfb9f358e0ecc88c3c8a913c51944cb (diff)
downloadlinux-stable-4484de23ba22e3023e9cbe4246a927ffb00db56f.tar.gz
linux-stable-4484de23ba22e3023e9cbe4246a927ffb00db56f.tar.bz2
linux-stable-4484de23ba22e3023e9cbe4246a927ffb00db56f.zip
wifi: mac80211: always hold sdata lock in chanctx assign/unassign
Due to all the multi-link handling, we now expose the fact that the sdata/vif is locked to drivers, e.g. when the driver uses ieee80211_set_monitor_channel(). This was true when a chanctx is added to or removed from a link, _except_ in monitor mode with the virtual sdata/vif. Change that, so that drivers can make that assumption. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230619161906.a5cf7534beda.I5b51664231abee27e02f222083df7ccf88722929@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/cfg.c16
-rw-r--r--net/mac80211/iface.c7
2 files changed, 18 insertions, 5 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index eea7028a46a7..e7ac24603892 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -913,24 +913,30 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
return 0;
- mutex_lock(&local->mtx);
if (local->use_chanctx) {
sdata = wiphy_dereference(local->hw.wiphy,
local->monitor_sdata);
if (sdata) {
+ sdata_lock(sdata);
+ mutex_lock(&local->mtx);
ieee80211_link_release_channel(&sdata->deflink);
ret = ieee80211_link_use_channel(&sdata->deflink,
chandef,
IEEE80211_CHANCTX_EXCLUSIVE);
+ mutex_unlock(&local->mtx);
+ sdata_unlock(sdata);
+ }
+ } else {
+ mutex_lock(&local->mtx);
+ if (local->open_count == local->monitors) {
+ local->_oper_chandef = *chandef;
+ ieee80211_hw_config(local, 0);
}
- } else if (local->open_count == local->monitors) {
- local->_oper_chandef = *chandef;
- ieee80211_hw_config(local, 0);
+ mutex_unlock(&local->mtx);
}
if (ret == 0)
local->monitor_chandef = *chandef;
- mutex_unlock(&local->mtx);
return ret;
}
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9518acf9643b..be586bc0b5b7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1133,6 +1133,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
wiphy_name(local->hw.wiphy));
sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
+ mutex_init(&sdata->wdev.mtx);
ieee80211_sdata_init(local, sdata);
@@ -1157,16 +1158,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
rcu_assign_pointer(local->monitor_sdata, sdata);
mutex_unlock(&local->iflist_mtx);
+ sdata_lock(sdata);
mutex_lock(&local->mtx);
ret = ieee80211_link_use_channel(&sdata->deflink, &local->monitor_chandef,
IEEE80211_CHANCTX_EXCLUSIVE);
mutex_unlock(&local->mtx);
+ sdata_unlock(sdata);
if (ret) {
mutex_lock(&local->iflist_mtx);
RCU_INIT_POINTER(local->monitor_sdata, NULL);
mutex_unlock(&local->iflist_mtx);
synchronize_net();
drv_remove_interface(local, sdata);
+ mutex_destroy(&sdata->wdev.mtx);
kfree(sdata);
return ret;
}
@@ -1202,12 +1206,15 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
synchronize_net();
+ sdata_lock(sdata);
mutex_lock(&local->mtx);
ieee80211_link_release_channel(&sdata->deflink);
mutex_unlock(&local->mtx);
+ sdata_unlock(sdata);
drv_remove_interface(local, sdata);
+ mutex_destroy(&sdata->wdev.mtx);
kfree(sdata);
}