Commit 4484de23 authored by Johannes Berg's avatar Johannes Berg

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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230619161906.a5cf7534beda.I5b51664231abee27e02f222083df7ccf88722929@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 5c1f9753
...@@ -913,24 +913,30 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, ...@@ -913,24 +913,30 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
return 0; return 0;
mutex_lock(&local->mtx);
if (local->use_chanctx) { if (local->use_chanctx) {
sdata = wiphy_dereference(local->hw.wiphy, sdata = wiphy_dereference(local->hw.wiphy,
local->monitor_sdata); local->monitor_sdata);
if (sdata) { if (sdata) {
sdata_lock(sdata);
mutex_lock(&local->mtx);
ieee80211_link_release_channel(&sdata->deflink); ieee80211_link_release_channel(&sdata->deflink);
ret = ieee80211_link_use_channel(&sdata->deflink, ret = ieee80211_link_use_channel(&sdata->deflink,
chandef, chandef,
IEEE80211_CHANCTX_EXCLUSIVE); 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) { mutex_unlock(&local->mtx);
local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
} }
if (ret == 0) if (ret == 0)
local->monitor_chandef = *chandef; local->monitor_chandef = *chandef;
mutex_unlock(&local->mtx);
return ret; return ret;
} }
......
...@@ -1133,6 +1133,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) ...@@ -1133,6 +1133,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
snprintf(sdata->name, IFNAMSIZ, "%s-monitor", snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
wiphy_name(local->hw.wiphy)); wiphy_name(local->hw.wiphy));
sdata->wdev.iftype = NL80211_IFTYPE_MONITOR; sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
mutex_init(&sdata->wdev.mtx);
ieee80211_sdata_init(local, sdata); ieee80211_sdata_init(local, sdata);
...@@ -1157,16 +1158,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) ...@@ -1157,16 +1158,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
rcu_assign_pointer(local->monitor_sdata, sdata); rcu_assign_pointer(local->monitor_sdata, sdata);
mutex_unlock(&local->iflist_mtx); mutex_unlock(&local->iflist_mtx);
sdata_lock(sdata);
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ret = ieee80211_link_use_channel(&sdata->deflink, &local->monitor_chandef, ret = ieee80211_link_use_channel(&sdata->deflink, &local->monitor_chandef,
IEEE80211_CHANCTX_EXCLUSIVE); IEEE80211_CHANCTX_EXCLUSIVE);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
sdata_unlock(sdata);
if (ret) { if (ret) {
mutex_lock(&local->iflist_mtx); mutex_lock(&local->iflist_mtx);
RCU_INIT_POINTER(local->monitor_sdata, NULL); RCU_INIT_POINTER(local->monitor_sdata, NULL);
mutex_unlock(&local->iflist_mtx); mutex_unlock(&local->iflist_mtx);
synchronize_net(); synchronize_net();
drv_remove_interface(local, sdata); drv_remove_interface(local, sdata);
mutex_destroy(&sdata->wdev.mtx);
kfree(sdata); kfree(sdata);
return ret; return ret;
} }
...@@ -1202,12 +1206,15 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) ...@@ -1202,12 +1206,15 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
synchronize_net(); synchronize_net();
sdata_lock(sdata);
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ieee80211_link_release_channel(&sdata->deflink); ieee80211_link_release_channel(&sdata->deflink);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
sdata_unlock(sdata);
drv_remove_interface(local, sdata); drv_remove_interface(local, sdata);
mutex_destroy(&sdata->wdev.mtx);
kfree(sdata); kfree(sdata);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment