aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_pathtbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_pathtbl.c')
-rw-r--r--net/mac80211/mesh_pathtbl.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 3cbdbb23d75a..a17f2b299045 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -55,10 +55,7 @@ static DEFINE_RWLOCK(pathtbl_resize_lock);
55 */ 55 */
56void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) 56void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
57{ 57{
58 __sta_info_get(sta); 58 rcu_assign_pointer(mpath->next_hop, sta);
59 if (mpath->next_hop)
60 sta_info_put(mpath->next_hop);
61 mpath->next_hop = sta;
62} 59}
63 60
64 61
@@ -236,7 +233,7 @@ void mesh_plink_broken(struct sta_info *sta)
236 struct mesh_path *mpath; 233 struct mesh_path *mpath;
237 struct mpath_node *node; 234 struct mpath_node *node;
238 struct hlist_node *p; 235 struct hlist_node *p;
239 struct net_device *dev = sta->dev; 236 struct net_device *dev = sta->sdata->dev;
240 int i; 237 int i;
241 238
242 rcu_read_lock(); 239 rcu_read_lock();
@@ -266,9 +263,9 @@ EXPORT_SYMBOL(mesh_plink_broken);
266 * 263 *
267 * RCU notes: this function is called when a mesh plink transitions from ESTAB 264 * RCU notes: this function is called when a mesh plink transitions from ESTAB
268 * to any other state, since ESTAB state is the only one that allows path 265 * to any other state, since ESTAB state is the only one that allows path
269 * creation. This will happen before the sta can be freed (since we hold 266 * creation. This will happen before the sta can be freed (because
270 * a reference to it) so any reader in a rcu read block will be protected 267 * sta_info_destroy() calls this) so any reader in a rcu read block will be
271 * against the plink dissapearing. 268 * protected against the plink disappearing.
272 */ 269 */
273void mesh_path_flush_by_nexthop(struct sta_info *sta) 270void mesh_path_flush_by_nexthop(struct sta_info *sta)
274{ 271{
@@ -280,7 +277,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
280 for_each_mesh_entry(mesh_paths, p, node, i) { 277 for_each_mesh_entry(mesh_paths, p, node, i) {
281 mpath = node->mpath; 278 mpath = node->mpath;
282 if (mpath->next_hop == sta) 279 if (mpath->next_hop == sta)
283 mesh_path_del(mpath->dst, mpath->dev); 280 mesh_path_del(mpath->dst, mpath->dev, true);
284 } 281 }
285} 282}
286 283
@@ -294,7 +291,7 @@ void mesh_path_flush(struct net_device *dev)
294 for_each_mesh_entry(mesh_paths, p, node, i) { 291 for_each_mesh_entry(mesh_paths, p, node, i) {
295 mpath = node->mpath; 292 mpath = node->mpath;
296 if (mpath->dev == dev) 293 if (mpath->dev == dev)
297 mesh_path_del(mpath->dst, mpath->dev); 294 mesh_path_del(mpath->dst, mpath->dev, false);
298 } 295 }
299} 296}
300 297
@@ -303,8 +300,8 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
303 struct mpath_node *node = container_of(rp, struct mpath_node, rcu); 300 struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
304 struct ieee80211_sub_if_data *sdata = 301 struct ieee80211_sub_if_data *sdata =
305 IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); 302 IEEE80211_DEV_TO_SUB_IF(node->mpath->dev);
306 if (node->mpath->next_hop) 303
307 sta_info_put(node->mpath->next_hop); 304 rcu_assign_pointer(node->mpath->next_hop, NULL);
308 atomic_dec(&sdata->u.sta.mpaths); 305 atomic_dec(&sdata->u.sta.mpaths);
309 kfree(node->mpath); 306 kfree(node->mpath);
310 kfree(node); 307 kfree(node);
@@ -319,9 +316,10 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
319 * Returns: 0 if succesful 316 * Returns: 0 if succesful
320 * 317 *
321 * State: if the path is being resolved, the deletion will be postponed until 318 * State: if the path is being resolved, the deletion will be postponed until
322 * the path resolution completes or times out. 319 * the path resolution completes or times out, unless the force parameter
320 * is given.
323 */ 321 */
324int mesh_path_del(u8 *addr, struct net_device *dev) 322int mesh_path_del(u8 *addr, struct net_device *dev, bool force)
325{ 323{
326 struct mesh_path *mpath; 324 struct mesh_path *mpath;
327 struct mpath_node *node; 325 struct mpath_node *node;
@@ -340,7 +338,7 @@ int mesh_path_del(u8 *addr, struct net_device *dev)
340 if (mpath->dev == dev && 338 if (mpath->dev == dev &&
341 memcmp(addr, mpath->dst, ETH_ALEN) == 0) { 339 memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
342 spin_lock_bh(&mpath->state_lock); 340 spin_lock_bh(&mpath->state_lock);
343 if (mpath->flags & MESH_PATH_RESOLVING) { 341 if (!force && mpath->flags & MESH_PATH_RESOLVING) {
344 mpath->flags |= MESH_PATH_DELETE; 342 mpath->flags |= MESH_PATH_DELETE;
345 } else { 343 } else {
346 mpath->flags |= MESH_PATH_RESOLVING; 344 mpath->flags |= MESH_PATH_RESOLVING;
@@ -510,7 +508,7 @@ void mesh_path_expire(struct net_device *dev)
510 time_after(jiffies, 508 time_after(jiffies,
511 mpath->exp_time + MESH_PATH_EXPIRE)) { 509 mpath->exp_time + MESH_PATH_EXPIRE)) {
512 spin_unlock_bh(&mpath->state_lock); 510 spin_unlock_bh(&mpath->state_lock);
513 mesh_path_del(mpath->dst, mpath->dev); 511 mesh_path_del(mpath->dst, mpath->dev, false);
514 } else 512 } else
515 spin_unlock_bh(&mpath->state_lock); 513 spin_unlock_bh(&mpath->state_lock);
516 } 514 }