diff options
Diffstat (limited to 'net/mac80211/mesh_pathtbl.c')
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 30 |
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 | */ |
56 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | 56 | void 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 | */ |
273 | void mesh_path_flush_by_nexthop(struct sta_info *sta) | 270 | void 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 | */ |
324 | int mesh_path_del(u8 *addr, struct net_device *dev) | 322 | int 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 | } |