Merge branch 'docs-move' of git://git.kernel.org/pub/scm/linux/kernel/git/rdunlap...
[pandora-kernel.git] / net / mac80211 / mesh_hwmp.c
index 5bf64d7..2b18053 100644 (file)
@@ -391,7 +391,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
                            (mpath->flags & MESH_PATH_SN_VALID)) {
                                if (SN_GT(mpath->sn, orig_sn) ||
                                    (mpath->sn == orig_sn &&
-                                    action == MPATH_PREQ &&
                                     new_metric >= mpath->metric)) {
                                        process = false;
                                        fresh_info = false;
@@ -561,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
 }
 
 
+static inline struct sta_info *
+next_hop_deref_protected(struct mesh_path *mpath)
+{
+       return rcu_dereference_protected(mpath->next_hop,
+                                        lockdep_is_held(&mpath->state_lock));
+}
+
+
 static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_mgmt *mgmt,
                                    u8 *prep_elem, u32 metric)
@@ -600,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
                spin_unlock_bh(&mpath->state_lock);
                goto fail;
        }
-       memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
+       memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);
        spin_unlock_bh(&mpath->state_lock);
        --ttl;
        flags = PREP_IE_FLAGS(prep_elem);
@@ -633,7 +640,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
        struct mesh_path *mpath;
        u8 ttl;
        u8 *ta, *target_addr;
-       u8 target_flags;
        u32 target_sn;
        u16 target_rcode;
 
@@ -644,7 +650,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
                return;
        }
        ttl--;
-       target_flags = PERR_IE_TARGET_FLAGS(perr_elem);
        target_addr = PERR_IE_TARGET_ADDR(perr_elem);
        target_sn = PERR_IE_TARGET_SN(perr_elem);
        target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
@@ -654,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
        if (mpath) {
                spin_lock_bh(&mpath->state_lock);
                if (mpath->flags & MESH_PATH_ACTIVE &&
-                   memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 &&
+                   memcmp(ta, next_hop_deref_protected(mpath)->sta.addr,
+                                                       ETH_ALEN) == 0 &&
                    (!(mpath->flags & MESH_PATH_SN_VALID) ||
                    SN_GT(target_sn, mpath->sn))) {
                        mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -675,12 +681,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct mesh_path *mpath;
-       u8 *ta;
        u8 ttl, flags, hopcount;
        u8 *orig_addr;
        u32 orig_sn, metric;
 
-       ta = mgmt->sa;
        ttl = rann->rann_ttl;
        if (ttl <= 1) {
                ifmsh->mshstats.dropped_frames_ttl++;
@@ -918,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
 {
        struct sk_buff *skb_to_free = NULL;
        struct mesh_path *mpath;
+       struct sta_info *next_hop;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        u8 *target_addr = hdr->addr3;
        int err = 0;
@@ -945,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
                        mesh_queue_preq(mpath,
                                        PREQ_Q_F_START | PREQ_Q_F_REFRESH);
                }
-               memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN);
+               next_hop = rcu_dereference(mpath->next_hop);
+               if (next_hop)
+                       memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
+               else
+                       err = -ENOENT;
        } else {
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
                if (!(mpath->flags & MESH_PATH_RESOLVING)) {
@@ -971,20 +980,11 @@ endlookup:
 
 void mesh_path_timer(unsigned long data)
 {
-       struct ieee80211_sub_if_data *sdata;
-       struct mesh_path *mpath;
-
-       rcu_read_lock();
-       mpath = (struct mesh_path *) data;
-       mpath = rcu_dereference(mpath);
-       if (!mpath)
-               goto endmpathtimer;
-       sdata = mpath->sdata;
+       struct mesh_path *mpath = (void *) data;
+       struct ieee80211_sub_if_data *sdata = mpath->sdata;
 
-       if (sdata->local->quiescing) {
-               rcu_read_unlock();
+       if (sdata->local->quiescing)
                return;
-       }
 
        spin_lock_bh(&mpath->state_lock);
        if (mpath->flags & MESH_PATH_RESOLVED ||
@@ -1001,8 +1001,6 @@ void mesh_path_timer(unsigned long data)
        }
 
        spin_unlock_bh(&mpath->state_lock);
-endmpathtimer:
-       rcu_read_unlock();
 }
 
 void