aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mesh.h3
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/mesh_pathtbl.c33
3 files changed, 25 insertions, 15 deletions
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index cc6854db156e..e1415c952e9c 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -32,6 +32,8 @@
32 * @MESH_PATH_RESOLVED: the mesh path can has been resolved 32 * @MESH_PATH_RESOLVED: the mesh path can has been resolved
33 * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination 33 * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination
34 * already queued up, waiting for the discovery process to start. 34 * already queued up, waiting for the discovery process to start.
35 * @MESH_PATH_DELETED: the mesh path has been deleted and should no longer
36 * be used
35 * 37 *
36 * MESH_PATH_RESOLVED is used by the mesh path timer to 38 * MESH_PATH_RESOLVED is used by the mesh path timer to
37 * decide when to stop or cancel the mesh path discovery. 39 * decide when to stop or cancel the mesh path discovery.
@@ -43,6 +45,7 @@ enum mesh_path_flags {
43 MESH_PATH_FIXED = BIT(3), 45 MESH_PATH_FIXED = BIT(3),
44 MESH_PATH_RESOLVED = BIT(4), 46 MESH_PATH_RESOLVED = BIT(4),
45 MESH_PATH_REQ_QUEUED = BIT(5), 47 MESH_PATH_REQ_QUEUED = BIT(5),
48 MESH_PATH_DELETED = BIT(6),
46}; 49};
47 50
48/** 51/**
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 5b6aec1a0630..2748cf627ee3 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1012,6 +1012,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
1012 goto enddiscovery; 1012 goto enddiscovery;
1013 1013
1014 spin_lock_bh(&mpath->state_lock); 1014 spin_lock_bh(&mpath->state_lock);
1015 if (mpath->flags & MESH_PATH_DELETED) {
1016 spin_unlock_bh(&mpath->state_lock);
1017 goto enddiscovery;
1018 }
1015 mpath->flags &= ~MESH_PATH_REQ_QUEUED; 1019 mpath->flags &= ~MESH_PATH_REQ_QUEUED;
1016 if (preq_node->flags & PREQ_Q_F_START) { 1020 if (preq_node->flags & PREQ_Q_F_START) {
1017 if (mpath->flags & MESH_PATH_RESOLVING) { 1021 if (mpath->flags & MESH_PATH_RESOLVING) {
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 7455397f8c3b..1c9412a29ca3 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -18,6 +18,8 @@
18#include "ieee80211_i.h" 18#include "ieee80211_i.h"
19#include "mesh.h" 19#include "mesh.h"
20 20
21static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath);
22
21static u32 mesh_table_hash(const void *addr, u32 len, u32 seed) 23static u32 mesh_table_hash(const void *addr, u32 len, u32 seed)
22{ 24{
23 /* Use last four bytes of hw addr as hash index */ 25 /* Use last four bytes of hw addr as hash index */
@@ -40,18 +42,12 @@ static inline bool mpath_expired(struct mesh_path *mpath)
40 !(mpath->flags & MESH_PATH_FIXED); 42 !(mpath->flags & MESH_PATH_FIXED);
41} 43}
42 44
43static void mesh_path_reclaim(struct rcu_head *rp) 45static void mesh_path_rht_free(void *ptr, void *tblptr)
44{
45 struct mesh_path *mpath = container_of(rp, struct mesh_path, rcu);
46
47 del_timer_sync(&mpath->timer);
48 kfree(mpath);
49}
50
51static void mesh_path_rht_free(void *ptr, void *unused_arg)
52{ 46{
53 struct mesh_path *mpath = ptr; 47 struct mesh_path *mpath = ptr;
54 call_rcu(&mpath->rcu, mesh_path_reclaim); 48 struct mesh_table *tbl = tblptr;
49
50 mesh_path_free_rcu(tbl, mpath);
55} 51}
56 52
57static struct mesh_table *mesh_table_alloc(void) 53static struct mesh_table *mesh_table_alloc(void)
@@ -77,7 +73,7 @@ static struct mesh_table *mesh_table_alloc(void)
77static void mesh_table_free(struct mesh_table *tbl) 73static void mesh_table_free(struct mesh_table *tbl)
78{ 74{
79 rhashtable_free_and_destroy(&tbl->rhead, 75 rhashtable_free_and_destroy(&tbl->rhead,
80 mesh_path_rht_free, NULL); 76 mesh_path_rht_free, tbl);
81 kfree(tbl); 77 kfree(tbl);
82} 78}
83 79
@@ -551,18 +547,25 @@ out:
551 rhashtable_walk_exit(&iter); 547 rhashtable_walk_exit(&iter);
552} 548}
553 549
554static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) 550static void mesh_path_free_rcu(struct mesh_table *tbl,
551 struct mesh_path *mpath)
555{ 552{
556 struct ieee80211_sub_if_data *sdata = mpath->sdata; 553 struct ieee80211_sub_if_data *sdata = mpath->sdata;
557 554
558 rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
559 spin_lock_bh(&mpath->state_lock); 555 spin_lock_bh(&mpath->state_lock);
560 mpath->flags |= MESH_PATH_RESOLVING; 556 mpath->flags |= MESH_PATH_RESOLVING | MESH_PATH_DELETED;
561 mesh_gate_del(tbl, mpath); 557 mesh_gate_del(tbl, mpath);
562 call_rcu(&mpath->rcu, mesh_path_reclaim);
563 spin_unlock_bh(&mpath->state_lock); 558 spin_unlock_bh(&mpath->state_lock);
559 del_timer_sync(&mpath->timer);
564 atomic_dec(&sdata->u.mesh.mpaths); 560 atomic_dec(&sdata->u.mesh.mpaths);
565 atomic_dec(&tbl->entries); 561 atomic_dec(&tbl->entries);
562 kfree_rcu(mpath, rcu);
563}
564
565static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
566{
567 rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
568 mesh_path_free_rcu(tbl, mpath);
566} 569}
567 570
568/** 571/**