]> err.no Git - linux-2.6/blobdiff - net/mac80211/mesh_pathtbl.c
mac80211: fix mesh_path and sta_info get_by_idx functions
[linux-2.6] / net / mac80211 / mesh_pathtbl.c
index 37094942e728bb2b2b8404a387d220b453bf3db1..5845dc21ce854ea535cb9fa69af2cbcb2b4d4889 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);
 }
 
 
@@ -101,7 +98,7 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev)
 /**
  * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
  * @idx: index
- * @dev: local interface
+ * @dev: local interface, or NULL for all entries
  *
  * Returns: pointer to the mesh path structure, or NULL if not found.
  *
@@ -114,7 +111,9 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev)
        int i;
        int j = 0;
 
-       for_each_mesh_entry(mesh_paths, p, node, i)
+       for_each_mesh_entry(mesh_paths, p, node, i) {
+               if (dev && node->mpath->dev != dev)
+                       continue;
                if (j++ == idx) {
                        if (MPATH_EXPIRED(node->mpath)) {
                                spin_lock_bh(&node->mpath->state_lock);
@@ -124,6 +123,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev)
                        }
                        return node->mpath;
                }
+       }
 
        return NULL;
 }
@@ -236,7 +236,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();
@@ -257,17 +257,18 @@ void mesh_plink_broken(struct sta_info *sta)
        }
        rcu_read_unlock();
 }
+EXPORT_SYMBOL(mesh_plink_broken);
 
 /**
  * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
  *
  * @sta - mesh peer to match
  *
- * 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.
+ * RCU notes: this function is called when a mesh plink transitions from
+ * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that
+ * allows path 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)
 {
@@ -302,8 +303,8 @@ 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);
+
+       del_timer_sync(&node->mpath->timer);
        atomic_dec(&sdata->u.sta.mpaths);
        kfree(node->mpath);
        kfree(node);
@@ -316,9 +317,6 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
  * @dev: local interface
  *
  * Returns: 0 if succesful
- *
- * State: if the path is being resolved, the deletion will be postponed until
- * the path resolution completes or times out.
  */
 int mesh_path_del(u8 *addr, struct net_device *dev)
 {
@@ -339,14 +337,10 @@ 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) {
-                               mpath->flags |= MESH_PATH_DELETE;
-                       } else {
-                               mpath->flags |= MESH_PATH_RESOLVING;
-                               hlist_del_rcu(&node->list);
-                               call_rcu(&node->rcu, mesh_path_node_reclaim);
-                               atomic_dec(&mesh_paths->entries);
-                       }
+                       mpath->flags |= MESH_PATH_RESOLVING;
+                       hlist_del_rcu(&node->list);
+                       call_rcu(&node->rcu, mesh_path_node_reclaim);
+                       atomic_dec(&mesh_paths->entries);
                        spin_unlock_bh(&mpath->state_lock);
                        goto enddel;
                }