[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190820223259.22348-39-willy@infradead.org>
Date: Tue, 20 Aug 2019 15:32:59 -0700
From: Matthew Wilcox <willy@...radead.org>
To: netdev@...r.kernel.org
Cc: "Matthew Wilcox (Oracle)" <willy@...radead.org>
Subject: [PATCH 38/38] mac80211: Convert function_inst_ids to XArray
From: "Matthew Wilcox (Oracle)" <willy@...radead.org>
Replae the func_lock with the internal XArray spinlock. Ensuring that
nan_func is fully initialised before dropping the lock allows us to
iterate the array while not holding the lock, avoiding the awkward dance
in ieee80211_reconfig_nan().
Signed-off-by: Matthew Wilcox (Oracle) <willy@...radead.org>
---
net/mac80211/cfg.c | 57 ++++++++++++++------------------------
net/mac80211/ieee80211_i.h | 9 ++----
net/mac80211/iface.c | 16 +++++------
net/mac80211/util.c | 30 ++++----------------
4 files changed, 37 insertions(+), 75 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 47d7670094a9..2ea45b7007db 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -266,7 +266,7 @@ static int ieee80211_add_nan_func(struct wiphy *wiphy,
struct cfg80211_nan_func *nan_func)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- int ret;
+ int ret, id;
if (sdata->vif.type != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
@@ -274,27 +274,22 @@ static int ieee80211_add_nan_func(struct wiphy *wiphy,
if (!ieee80211_sdata_running(sdata))
return -ENETDOWN;
- spin_lock_bh(&sdata->u.nan.func_lock);
-
- ret = idr_alloc(&sdata->u.nan.function_inst_ids,
- nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
- GFP_ATOMIC);
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ xa_lock_bh(&sdata->u.nan.functions);
+ ret = __xa_alloc(&sdata->u.nan.functions, &id, nan_func,
+ XA_LIMIT(0, sdata->local->hw.max_nan_de_entries),
+ GFP_KERNEL);
+ if (ret == 0)
+ nan_func->instance_id = id;
+ xa_unlock_bh(&sdata->u.nan.functions);
if (ret < 0)
return ret;
- nan_func->instance_id = ret;
-
WARN_ON(nan_func->instance_id == 0);
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,
- nan_func->instance_id);
- spin_unlock_bh(&sdata->u.nan.func_lock);
- }
+ if (ret)
+ xa_erase_bh(&sdata->u.nan.functions, nan_func->instance_id);
return ret;
}
@@ -304,11 +299,11 @@ ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
u64 cookie)
{
struct cfg80211_nan_func *func;
- int id;
+ unsigned long id;
- lockdep_assert_held(&sdata->u.nan.func_lock);
+ lockdep_assert_held(&sdata->u.nan.functions.xa_lock);
- idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
+ xa_for_each(&sdata->u.nan.functions, id, func) {
if (func->cookie == cookie)
return func;
}
@@ -327,13 +322,13 @@ static void ieee80211_del_nan_func(struct wiphy *wiphy,
!ieee80211_sdata_running(sdata))
return;
- spin_lock_bh(&sdata->u.nan.func_lock);
+ xa_lock_bh(&sdata->u.nan.functions);
func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
if (func)
instance_id = func->instance_id;
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ xa_unlock_bh(&sdata->u.nan.functions);
if (instance_id)
drv_del_nan_func(sdata->local, sdata, instance_id);
@@ -3766,19 +3761,11 @@ 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);
-
- func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
- if (WARN_ON(!func)) {
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ func = xa_erase_bh(&sdata->u.nan.functions, inst_id);
+ if (WARN_ON(!func))
return;
- }
cookie = func->cookie;
- idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
-
- spin_unlock_bh(&sdata->u.nan.func_lock);
-
cfg80211_free_nan_func(func);
cfg80211_nan_func_terminated(ieee80211_vif_to_wdev(vif), inst_id,
@@ -3796,16 +3783,14 @@ 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);
-
- func = idr_find(&sdata->u.nan.function_inst_ids, match->inst_id);
+ xa_lock_bh(&sdata->u.nan.functions);
+ func = xa_load(&sdata->u.nan.functions, match->inst_id);
if (WARN_ON(!func)) {
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ xa_unlock_bh(&sdata->u.nan.functions);
return;
}
match->cookie = func->cookie;
-
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ xa_unlock_bh(&sdata->u.nan.functions);
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 ade005892099..7be25939a6bf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -23,7 +23,7 @@
#include <linux/spinlock.h>
#include <linux/etherdevice.h>
#include <linux/leds.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <linux/rhashtable.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
@@ -862,14 +862,11 @@ struct ieee80211_if_mntr {
* struct ieee80211_if_nan - NAN state
*
* @conf: current NAN configuration
- * @func_ids: a bitmap of available instance_id's
+ * @functions: NAN function pointers
*/
struct ieee80211_if_nan {
struct cfg80211_nan_conf conf;
-
- /* protects function_inst_ids */
- spinlock_t func_lock;
- struct idr function_inst_ids;
+ struct xarray functions;
};
struct ieee80211_sub_if_data {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8dc6580e1787..022e2eb6a46c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -802,6 +802,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
struct cfg80211_chan_def chandef;
bool cancel_scan;
struct cfg80211_nan_func *func;
+ unsigned long index;
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
@@ -961,15 +962,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
break;
case NL80211_IFTYPE_NAN:
/* clean all the functions */
- spin_lock_bh(&sdata->u.nan.func_lock);
-
- idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
- idr_remove(&sdata->u.nan.function_inst_ids, i);
+ xa_lock_bh(&sdata->u.nan.functions);
+ xa_for_each(&sdata->u.nan.functions, index, func) {
+ __xa_erase(&sdata->u.nan.functions, index);
cfg80211_free_nan_func(func);
}
- idr_destroy(&sdata->u.nan.function_inst_ids);
-
- spin_unlock_bh(&sdata->u.nan.func_lock);
+ xa_unlock_bh(&sdata->u.nan.functions);
break;
case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */
@@ -1463,8 +1461,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.bssid = NULL;
break;
case NL80211_IFTYPE_NAN:
- idr_init(&sdata->u.nan.function_inst_ids);
- spin_lock_init(&sdata->u.nan.func_lock);
+ xa_init_flags(&sdata->u.nan.functions,
+ XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH);
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
case NL80211_IFTYPE_AP_VLAN:
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 286c7ee35e63..4996a3c01205 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2082,42 +2082,24 @@ static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
{
- struct cfg80211_nan_func *func, **funcs;
- int res, id, i = 0;
+ struct cfg80211_nan_func *func;
+ unsigned long id;
+ int res;
res = drv_start_nan(sdata->local, sdata,
&sdata->u.nan.conf);
if (WARN_ON(res))
return res;
- funcs = kcalloc(sdata->local->hw.max_nan_de_entries + 1,
- sizeof(*funcs),
- GFP_KERNEL);
- if (!funcs)
- return -ENOMEM;
-
- /* Add all the functions:
- * 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);
-
- idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id)
- funcs[i++] = func;
-
- spin_unlock_bh(&sdata->u.nan.func_lock);
-
- for (i = 0; funcs[i]; i++) {
- res = drv_add_nan_func(sdata->local, sdata, funcs[i]);
+ xa_for_each(&sdata->u.nan.functions, id, func) {
+ res = drv_add_nan_func(sdata->local, sdata, func);
if (WARN_ON(res))
ieee80211_nan_func_terminated(&sdata->vif,
- funcs[i]->instance_id,
+ func->instance_id,
NL80211_NAN_FUNC_TERM_REASON_ERROR,
GFP_KERNEL);
}
- kfree(funcs);
-
return 0;
}
--
2.23.0.rc1
Powered by blists - more mailing lists