mac80211: don't clear next_hop in path reclaim
[safe/jmp/linux-2.6] / net / mac80211 / mesh_pathtbl.c
index 3cbdbb2..ab4d757 100644 (file)
@@ -55,10 +55,7 @@ static DEFINE_RWLOCK(pathtbl_resize_lock);
  */
 void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
 {
-       __sta_info_get(sta);
-       if (mpath->next_hop)
-               sta_info_put(mpath->next_hop);
-       mpath->next_hop = sta;
+       rcu_assign_pointer(mpath->next_hop, sta);
 }
 
 
@@ -236,7 +233,7 @@ void mesh_plink_broken(struct sta_info *sta)
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_node *p;
-       struct net_device *dev = sta->dev;
+       struct net_device *dev = sta->sdata->dev;
        int i;
 
        rcu_read_lock();
@@ -266,9 +263,9 @@ EXPORT_SYMBOL(mesh_plink_broken);
  *
  * RCU notes: this function is called when a mesh plink transitions from ESTAB
  * to any other state, since ESTAB state is the only one that allows path
- * creation. This will happen before the sta can be freed (since we hold
- * a reference to it) so any reader in a rcu read block will be protected
- * against the plink dissapearing.
+ * creation. This will happen before the sta can be freed (because
+ * sta_info_destroy() calls this) so any reader in a rcu read block will be
+ * protected against the plink disappearing.
  */
 void mesh_path_flush_by_nexthop(struct sta_info *sta)
 {
@@ -280,7 +277,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
        for_each_mesh_entry(mesh_paths, p, node, i) {
                mpath = node->mpath;
                if (mpath->next_hop == sta)
-                       mesh_path_del(mpath->dst, mpath->dev);
+                       mesh_path_del(mpath->dst, mpath->dev, true);
        }
 }
 
@@ -294,7 +291,7 @@ void mesh_path_flush(struct net_device *dev)
        for_each_mesh_entry(mesh_paths, p, node, i) {
                mpath = node->mpath;
                if (mpath->dev == dev)
-                       mesh_path_del(mpath->dst, mpath->dev);
+                       mesh_path_del(mpath->dst, mpath->dev, false);
        }
 }
 
@@ -303,8 +300,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
        struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
        struct ieee80211_sub_if_data *sdata =
                IEEE80211_DEV_TO_SUB_IF(node->mpath->dev);
-       if (node->mpath->next_hop)
-               sta_info_put(node->mpath->next_hop);
+
        atomic_dec(&sdata->u.sta.mpaths);
        kfree(node->mpath);
        kfree(node);
@@ -319,9 +315,10 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
  * Returns: 0 if succesful
  *
  * State: if the path is being resolved, the deletion will be postponed until
- * the path resolution completes or times out.
+ * the path resolution completes or times out, unless the force parameter
+ * is given.
  */
-int mesh_path_del(u8 *addr, struct net_device *dev)
+int mesh_path_del(u8 *addr, struct net_device *dev, bool force)
 {
        struct mesh_path *mpath;
        struct mpath_node *node;
@@ -340,7 +337,7 @@ int mesh_path_del(u8 *addr, struct net_device *dev)
                if (mpath->dev == dev &&
                                memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
                        spin_lock_bh(&mpath->state_lock);
-                       if (mpath->flags & MESH_PATH_RESOLVING) {
+                       if (!force && mpath->flags & MESH_PATH_RESOLVING) {
                                mpath->flags |= MESH_PATH_DELETE;
                        } else {
                                mpath->flags |= MESH_PATH_RESOLVING;
@@ -510,7 +507,7 @@ void mesh_path_expire(struct net_device *dev)
                        time_after(jiffies,
                         mpath->exp_time + MESH_PATH_EXPIRE)) {
                        spin_unlock_bh(&mpath->state_lock);
-                       mesh_path_del(mpath->dst, mpath->dev);
+                       mesh_path_del(mpath->dst, mpath->dev, false);
                } else
                        spin_unlock_bh(&mpath->state_lock);
        }