diff options
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 4 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 33 |
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 | ||
21 | static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath); | ||
22 | |||
21 | static u32 mesh_table_hash(const void *addr, u32 len, u32 seed) | 23 | static 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 | ||
43 | static void mesh_path_reclaim(struct rcu_head *rp) | 45 | static 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 | |||
51 | static 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 | ||
57 | static struct mesh_table *mesh_table_alloc(void) | 53 | static struct mesh_table *mesh_table_alloc(void) |
@@ -77,7 +73,7 @@ static struct mesh_table *mesh_table_alloc(void) | |||
77 | static void mesh_table_free(struct mesh_table *tbl) | 73 | static 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 | ||
554 | static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) | 550 | static 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 | |||
565 | static 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 | /** |