diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b6163dcc7e92..3a6c5fed2420 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -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); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 53d783769642..8d5f9a725fdf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -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 { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7518dcbcdf1c..f0a5a675c5a5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -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: diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d1bb6353908d..f47dd58770ad 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -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) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 38b0c42c4c13..36795529ff82 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -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]);