Skip to content

Commit a31687e

Browse files
committed
Merge tag 'mac80211-for-davem-2019-02-15' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says: ==================== Just a few fixes this time: * mesh rhashtable fixes from Herbert * a small error path fix when starting AP interfaces ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 24f0a48 + 83e37e0 commit a31687e

File tree

3 files changed

+57
-110
lines changed

3 files changed

+57
-110
lines changed

net/mac80211/cfg.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
941941
BSS_CHANGED_P2P_PS |
942942
BSS_CHANGED_TXPOWER;
943943
int err;
944+
int prev_beacon_int;
944945

945946
old = sdata_dereference(sdata->u.ap.beacon, sdata);
946947
if (old)
@@ -963,6 +964,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
963964

964965
sdata->needed_rx_chains = sdata->local->rx_chains;
965966

967+
prev_beacon_int = sdata->vif.bss_conf.beacon_int;
966968
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
967969

968970
if (params->he_cap)
@@ -974,8 +976,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
974976
if (!err)
975977
ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
976978
mutex_unlock(&local->mtx);
977-
if (err)
979+
if (err) {
980+
sdata->vif.bss_conf.beacon_int = prev_beacon_int;
978981
return err;
982+
}
979983

980984
/*
981985
* Apply control port protocol, this allows us to

net/mac80211/mesh.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ enum mesh_deferred_task_flags {
7070
* @dst: mesh path destination mac address
7171
* @mpp: mesh proxy mac address
7272
* @rhash: rhashtable list pointer
73+
* @walk_list: linked list containing all mesh_path objects.
7374
* @gate_list: list pointer for known gates list
7475
* @sdata: mesh subif
7576
* @next_hop: mesh neighbor to which frames for this destination will be
@@ -105,6 +106,7 @@ struct mesh_path {
105106
u8 dst[ETH_ALEN];
106107
u8 mpp[ETH_ALEN]; /* used for MPP or MAP */
107108
struct rhash_head rhash;
109+
struct hlist_node walk_list;
108110
struct hlist_node gate_list;
109111
struct ieee80211_sub_if_data *sdata;
110112
struct sta_info __rcu *next_hop;
@@ -133,12 +135,16 @@ struct mesh_path {
133135
* gate's mpath may or may not be resolved and active.
134136
* @gates_lock: protects updates to known_gates
135137
* @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr
138+
* @walk_head: linked list containging all mesh_path objects
139+
* @walk_lock: lock protecting walk_head
136140
* @entries: number of entries in the table
137141
*/
138142
struct mesh_table {
139143
struct hlist_head known_gates;
140144
spinlock_t gates_lock;
141145
struct rhashtable rhead;
146+
struct hlist_head walk_head;
147+
spinlock_t walk_lock;
142148
atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
143149
};
144150

net/mac80211/mesh_pathtbl.c

Lines changed: 46 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ static struct mesh_table *mesh_table_alloc(void)
5959
return NULL;
6060

6161
INIT_HLIST_HEAD(&newtbl->known_gates);
62+
INIT_HLIST_HEAD(&newtbl->walk_head);
6263
atomic_set(&newtbl->entries, 0);
6364
spin_lock_init(&newtbl->gates_lock);
65+
spin_lock_init(&newtbl->walk_lock);
6466

6567
return newtbl;
6668
}
@@ -249,28 +251,15 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
249251
static struct mesh_path *
250252
__mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx)
251253
{
252-
int i = 0, ret;
253-
struct mesh_path *mpath = NULL;
254-
struct rhashtable_iter iter;
255-
256-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
257-
if (ret)
258-
return NULL;
259-
260-
rhashtable_walk_start(&iter);
254+
int i = 0;
255+
struct mesh_path *mpath;
261256

262-
while ((mpath = rhashtable_walk_next(&iter))) {
263-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
264-
continue;
265-
if (IS_ERR(mpath))
266-
break;
257+
hlist_for_each_entry_rcu(mpath, &tbl->walk_head, walk_list) {
267258
if (i++ == idx)
268259
break;
269260
}
270-
rhashtable_walk_stop(&iter);
271-
rhashtable_walk_exit(&iter);
272261

273-
if (IS_ERR(mpath) || !mpath)
262+
if (!mpath)
274263
return NULL;
275264

276265
if (mpath_expired(mpath)) {
@@ -432,6 +421,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
432421
return ERR_PTR(-ENOMEM);
433422

434423
tbl = sdata->u.mesh.mesh_paths;
424+
spin_lock_bh(&tbl->walk_lock);
435425
do {
436426
ret = rhashtable_lookup_insert_fast(&tbl->rhead,
437427
&new_mpath->rhash,
@@ -441,20 +431,20 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
441431
mpath = rhashtable_lookup_fast(&tbl->rhead,
442432
dst,
443433
mesh_rht_params);
444-
434+
else if (!ret)
435+
hlist_add_head(&new_mpath->walk_list, &tbl->walk_head);
445436
} while (unlikely(ret == -EEXIST && !mpath));
437+
spin_unlock_bh(&tbl->walk_lock);
446438

447-
if (ret && ret != -EEXIST)
448-
return ERR_PTR(ret);
449-
450-
/* At this point either new_mpath was added, or we found a
451-
* matching entry already in the table; in the latter case
452-
* free the unnecessary new entry.
453-
*/
454-
if (ret == -EEXIST) {
439+
if (ret) {
455440
kfree(new_mpath);
441+
442+
if (ret != -EEXIST)
443+
return ERR_PTR(ret);
444+
456445
new_mpath = mpath;
457446
}
447+
458448
sdata->u.mesh.mesh_paths_generation++;
459449
return new_mpath;
460450
}
@@ -480,9 +470,17 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
480470

481471
memcpy(new_mpath->mpp, mpp, ETH_ALEN);
482472
tbl = sdata->u.mesh.mpp_paths;
473+
474+
spin_lock_bh(&tbl->walk_lock);
483475
ret = rhashtable_lookup_insert_fast(&tbl->rhead,
484476
&new_mpath->rhash,
485477
mesh_rht_params);
478+
if (!ret)
479+
hlist_add_head_rcu(&new_mpath->walk_list, &tbl->walk_head);
480+
spin_unlock_bh(&tbl->walk_lock);
481+
482+
if (ret)
483+
kfree(new_mpath);
486484

487485
sdata->u.mesh.mpp_paths_generation++;
488486
return ret;
@@ -503,20 +501,9 @@ void mesh_plink_broken(struct sta_info *sta)
503501
struct mesh_table *tbl = sdata->u.mesh.mesh_paths;
504502
static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
505503
struct mesh_path *mpath;
506-
struct rhashtable_iter iter;
507-
int ret;
508-
509-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
510-
if (ret)
511-
return;
512504

513-
rhashtable_walk_start(&iter);
514-
515-
while ((mpath = rhashtable_walk_next(&iter))) {
516-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
517-
continue;
518-
if (IS_ERR(mpath))
519-
break;
505+
rcu_read_lock();
506+
hlist_for_each_entry_rcu(mpath, &tbl->walk_head, walk_list) {
520507
if (rcu_access_pointer(mpath->next_hop) == sta &&
521508
mpath->flags & MESH_PATH_ACTIVE &&
522509
!(mpath->flags & MESH_PATH_FIXED)) {
@@ -530,8 +517,7 @@ void mesh_plink_broken(struct sta_info *sta)
530517
WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
531518
}
532519
}
533-
rhashtable_walk_stop(&iter);
534-
rhashtable_walk_exit(&iter);
520+
rcu_read_unlock();
535521
}
536522

537523
static void mesh_path_free_rcu(struct mesh_table *tbl,
@@ -551,6 +537,7 @@ static void mesh_path_free_rcu(struct mesh_table *tbl,
551537

552538
static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
553539
{
540+
hlist_del_rcu(&mpath->walk_list);
554541
rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
555542
mesh_path_free_rcu(tbl, mpath);
556543
}
@@ -571,79 +558,41 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
571558
struct ieee80211_sub_if_data *sdata = sta->sdata;
572559
struct mesh_table *tbl = sdata->u.mesh.mesh_paths;
573560
struct mesh_path *mpath;
574-
struct rhashtable_iter iter;
575-
int ret;
576-
577-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
578-
if (ret)
579-
return;
580-
581-
rhashtable_walk_start(&iter);
582-
583-
while ((mpath = rhashtable_walk_next(&iter))) {
584-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
585-
continue;
586-
if (IS_ERR(mpath))
587-
break;
561+
struct hlist_node *n;
588562

563+
spin_lock_bh(&tbl->walk_lock);
564+
hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
589565
if (rcu_access_pointer(mpath->next_hop) == sta)
590566
__mesh_path_del(tbl, mpath);
591567
}
592-
593-
rhashtable_walk_stop(&iter);
594-
rhashtable_walk_exit(&iter);
568+
spin_unlock_bh(&tbl->walk_lock);
595569
}
596570

597571
static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
598572
const u8 *proxy)
599573
{
600574
struct mesh_table *tbl = sdata->u.mesh.mpp_paths;
601575
struct mesh_path *mpath;
602-
struct rhashtable_iter iter;
603-
int ret;
604-
605-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
606-
if (ret)
607-
return;
608-
609-
rhashtable_walk_start(&iter);
610-
611-
while ((mpath = rhashtable_walk_next(&iter))) {
612-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
613-
continue;
614-
if (IS_ERR(mpath))
615-
break;
576+
struct hlist_node *n;
616577

578+
spin_lock_bh(&tbl->walk_lock);
579+
hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
617580
if (ether_addr_equal(mpath->mpp, proxy))
618581
__mesh_path_del(tbl, mpath);
619582
}
620-
621-
rhashtable_walk_stop(&iter);
622-
rhashtable_walk_exit(&iter);
583+
spin_unlock_bh(&tbl->walk_lock);
623584
}
624585

625586
static void table_flush_by_iface(struct mesh_table *tbl)
626587
{
627588
struct mesh_path *mpath;
628-
struct rhashtable_iter iter;
629-
int ret;
630-
631-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
632-
if (ret)
633-
return;
634-
635-
rhashtable_walk_start(&iter);
589+
struct hlist_node *n;
636590

637-
while ((mpath = rhashtable_walk_next(&iter))) {
638-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
639-
continue;
640-
if (IS_ERR(mpath))
641-
break;
591+
spin_lock_bh(&tbl->walk_lock);
592+
hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
642593
__mesh_path_del(tbl, mpath);
643594
}
644-
645-
rhashtable_walk_stop(&iter);
646-
rhashtable_walk_exit(&iter);
595+
spin_unlock_bh(&tbl->walk_lock);
647596
}
648597

649598
/**
@@ -675,15 +624,15 @@ static int table_path_del(struct mesh_table *tbl,
675624
{
676625
struct mesh_path *mpath;
677626

678-
rcu_read_lock();
627+
spin_lock_bh(&tbl->walk_lock);
679628
mpath = rhashtable_lookup_fast(&tbl->rhead, addr, mesh_rht_params);
680629
if (!mpath) {
681630
rcu_read_unlock();
682631
return -ENXIO;
683632
}
684633

685634
__mesh_path_del(tbl, mpath);
686-
rcu_read_unlock();
635+
spin_unlock_bh(&tbl->walk_lock);
687636
return 0;
688637
}
689638

@@ -854,28 +803,16 @@ void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata,
854803
struct mesh_table *tbl)
855804
{
856805
struct mesh_path *mpath;
857-
struct rhashtable_iter iter;
858-
int ret;
806+
struct hlist_node *n;
859807

860-
ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_KERNEL);
861-
if (ret)
862-
return;
863-
864-
rhashtable_walk_start(&iter);
865-
866-
while ((mpath = rhashtable_walk_next(&iter))) {
867-
if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
868-
continue;
869-
if (IS_ERR(mpath))
870-
break;
808+
spin_lock_bh(&tbl->walk_lock);
809+
hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
871810
if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
872811
(!(mpath->flags & MESH_PATH_FIXED)) &&
873812
time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
874813
__mesh_path_del(tbl, mpath);
875814
}
876-
877-
rhashtable_walk_stop(&iter);
878-
rhashtable_walk_exit(&iter);
815+
spin_unlock_bh(&tbl->walk_lock);
879816
}
880817

881818
void mesh_path_expire(struct ieee80211_sub_if_data *sdata)

0 commit comments

Comments
 (0)