mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 03:11:11 -04:00
wifi: mac80211: run NAN DE code only when appropriate
NAN DE (Discovery Engine) may be handled in the device or in user space. When handled in user space, all the NAN func management code should not run. Moreover, devices with user space DE should not provide the add/del_nan_func callbaks. For such devices, ieee80211_reconfig_nan will always fail. Make it clear what parts of ieee80211_if_nan are relevant to DE management, and touch those only when DE is offloaded. Add a check that makes sure that a driver doesn't register with add_del/nan_func callbacks if DE is in user space. Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260326121156.6665f64865cd.Iee24bef3bae2e1d502216192e760c1e699d271c9@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
b16df0dacb
commit
23eab70e30
@@ -502,12 +502,15 @@ static int ieee80211_add_nan_func(struct wiphy *wiphy,
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
return -ENETDOWN;
|
||||
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
if (WARN_ON(wiphy->nan_capa.flags & WIPHY_NAN_FLAGS_USERSPACE_DE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = idr_alloc(&sdata->u.nan.function_inst_ids,
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
ret = idr_alloc(&sdata->u.nan.de.function_inst_ids,
|
||||
nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
|
||||
GFP_ATOMIC);
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -518,10 +521,10 @@ static int ieee80211_add_nan_func(struct wiphy *wiphy,
|
||||
|
||||
ret = drv_add_nan_func(sdata->local, sdata, nan_func);
|
||||
if (ret) {
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
idr_remove(&sdata->u.nan.function_inst_ids,
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
idr_remove(&sdata->u.nan.de.function_inst_ids,
|
||||
nan_func->instance_id);
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -534,9 +537,9 @@ ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_nan_func *func;
|
||||
int id;
|
||||
|
||||
lockdep_assert_held(&sdata->u.nan.func_lock);
|
||||
lockdep_assert_held(&sdata->u.nan.de.func_lock);
|
||||
|
||||
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
|
||||
idr_for_each_entry(&sdata->u.nan.de.function_inst_ids, func, id) {
|
||||
if (func->cookie == cookie)
|
||||
return func;
|
||||
}
|
||||
@@ -555,13 +558,16 @@ static void ieee80211_del_nan_func(struct wiphy *wiphy,
|
||||
!ieee80211_sdata_running(sdata))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
if (WARN_ON(wiphy->nan_capa.flags & WIPHY_NAN_FLAGS_USERSPACE_DE))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
|
||||
if (func)
|
||||
instance_id = func->instance_id;
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
if (instance_id)
|
||||
drv_del_nan_func(sdata->local, sdata, instance_id);
|
||||
@@ -4888,18 +4894,22 @@ void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
if (WARN_ON(sdata->local->hw.wiphy->nan_capa.flags &
|
||||
WIPHY_NAN_FLAGS_USERSPACE_DE))
|
||||
return;
|
||||
|
||||
func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
func = idr_find(&sdata->u.nan.de.function_inst_ids, inst_id);
|
||||
if (WARN_ON(!func)) {
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
cookie = func->cookie;
|
||||
idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
|
||||
idr_remove(&sdata->u.nan.de.function_inst_ids, inst_id);
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
cfg80211_free_nan_func(func);
|
||||
|
||||
@@ -4918,16 +4928,20 @@ void ieee80211_nan_func_match(struct ieee80211_vif *vif,
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
if (WARN_ON(sdata->local->hw.wiphy->nan_capa.flags &
|
||||
WIPHY_NAN_FLAGS_USERSPACE_DE))
|
||||
return;
|
||||
|
||||
func = idr_find(&sdata->u.nan.function_inst_ids, match->inst_id);
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
func = idr_find(&sdata->u.nan.de.function_inst_ids, match->inst_id);
|
||||
if (WARN_ON(!func)) {
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
return;
|
||||
}
|
||||
match->cookie = func->cookie;
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
cfg80211_nan_match(ieee80211_vif_to_wdev(vif), match, gfp);
|
||||
}
|
||||
|
||||
@@ -987,16 +987,19 @@ struct ieee80211_if_mntr {
|
||||
*
|
||||
* @conf: current NAN configuration
|
||||
* @started: true iff NAN is started
|
||||
* @func_lock: lock for @func_inst_ids
|
||||
* @function_inst_ids: a bitmap of available instance_id's
|
||||
* @de: Discovery Engine state (only valid if !WIPHY_NAN_FLAGS_USERSPACE_DE)
|
||||
* @de.func_lock: lock for @de.function_inst_ids
|
||||
* @de.function_inst_ids: a bitmap of available instance_id's
|
||||
*/
|
||||
struct ieee80211_if_nan {
|
||||
struct cfg80211_nan_conf conf;
|
||||
bool started;
|
||||
|
||||
/* protects function_inst_ids */
|
||||
spinlock_t func_lock;
|
||||
struct idr function_inst_ids;
|
||||
struct {
|
||||
/* protects function_inst_ids */
|
||||
spinlock_t func_lock;
|
||||
struct idr function_inst_ids;
|
||||
} de;
|
||||
};
|
||||
|
||||
struct ieee80211_link_data_managed {
|
||||
|
||||
@@ -622,15 +622,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
/* clean all the functions */
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
if (!(local->hw.wiphy->nan_capa.flags &
|
||||
WIPHY_NAN_FLAGS_USERSPACE_DE)) {
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
|
||||
idr_remove(&sdata->u.nan.function_inst_ids, i);
|
||||
cfg80211_free_nan_func(func);
|
||||
idr_for_each_entry(&sdata->u.nan.de.function_inst_ids,
|
||||
func, i) {
|
||||
idr_remove(&sdata->u.nan.de.function_inst_ids, i);
|
||||
cfg80211_free_nan_func(func);
|
||||
}
|
||||
idr_destroy(&sdata->u.nan.de.function_inst_ids);
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
}
|
||||
idr_destroy(&sdata->u.nan.function_inst_ids);
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
break;
|
||||
default:
|
||||
wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
|
||||
@@ -1942,8 +1946,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||
MONITOR_FLAG_OTHER_BSS;
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
idr_init(&sdata->u.nan.function_inst_ids);
|
||||
spin_lock_init(&sdata->u.nan.func_lock);
|
||||
if (!(sdata->local->hw.wiphy->nan_capa.flags &
|
||||
WIPHY_NAN_FLAGS_USERSPACE_DE)) {
|
||||
idr_init(&sdata->u.nan.de.function_inst_ids);
|
||||
spin_lock_init(&sdata->u.nan.de.func_lock);
|
||||
}
|
||||
sdata->vif.bss_conf.bssid = sdata->vif.addr;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
|
||||
@@ -1157,7 +1157,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
|
||||
if (WARN_ON(local->hw.wiphy->interface_modes &
|
||||
BIT(NL80211_IFTYPE_NAN) &&
|
||||
(!local->ops->start_nan || !local->ops->stop_nan)))
|
||||
((!local->ops->start_nan || !local->ops->stop_nan) ||
|
||||
(local->hw.wiphy->nan_capa.flags & WIPHY_NAN_FLAGS_USERSPACE_DE &&
|
||||
(local->ops->add_nan_func || local->ops->del_nan_func)))))
|
||||
return -EINVAL;
|
||||
|
||||
if (hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO) {
|
||||
|
||||
@@ -1754,6 +1754,10 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
|
||||
if (WARN_ON(res))
|
||||
return res;
|
||||
|
||||
if (sdata->local->hw.wiphy->nan_capa.flags &
|
||||
WIPHY_NAN_FLAGS_USERSPACE_DE)
|
||||
return 0;
|
||||
|
||||
funcs = kzalloc_objs(*funcs, sdata->local->hw.max_nan_de_entries + 1);
|
||||
if (!funcs)
|
||||
return -ENOMEM;
|
||||
@@ -1762,12 +1766,12 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
|
||||
* This is a little bit ugly. We need to call a potentially sleeping
|
||||
* callback for each NAN function, so we can't hold the spinlock.
|
||||
*/
|
||||
spin_lock_bh(&sdata->u.nan.func_lock);
|
||||
spin_lock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id)
|
||||
idr_for_each_entry(&sdata->u.nan.de.function_inst_ids, func, id)
|
||||
funcs[i++] = func;
|
||||
|
||||
spin_unlock_bh(&sdata->u.nan.func_lock);
|
||||
spin_unlock_bh(&sdata->u.nan.de.func_lock);
|
||||
|
||||
for (i = 0; funcs[i]; i++) {
|
||||
res = drv_add_nan_func(sdata->local, sdata, funcs[i]);
|
||||
|
||||
Reference in New Issue
Block a user