static void gw_node_free_ref(struct gw_node *gw_node)
  {
        if (atomic_dec_and_test(&gw_node->refcount))
 -              call_rcu(&gw_node->rcu, gw_node_free_rcu);
 +              kfree_rcu(gw_node, rcu);
  }
  
- void *gw_get_selected(struct bat_priv *bat_priv)
+ static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv)
  {
-       struct gw_node *curr_gateway_tmp;
-       struct orig_node *orig_node = NULL;
+       struct gw_node *gw_node;
  
        rcu_read_lock();
-       curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
-       if (!curr_gateway_tmp)
-               goto out;
- 
-       orig_node = curr_gateway_tmp->orig_node;
-       if (!orig_node)
+       gw_node = rcu_dereference(bat_priv->curr_gw);
+       if (!gw_node)
                goto out;
  
-       if (!atomic_inc_not_zero(&orig_node->refcount))
-               orig_node = NULL;
+       if (!atomic_inc_not_zero(&gw_node->refcount))
+               gw_node = NULL;
  
  out:
        rcu_read_unlock();
 
  static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
  {
        if (atomic_dec_and_test(&softif_neigh->refcount))
 -              call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
 +              kfree_rcu(softif_neigh, rcu);
  }
  
- void softif_neigh_purge(struct bat_priv *bat_priv)
+ static void softif_neigh_vid_free_rcu(struct rcu_head *rcu)
  {
-       struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+       struct softif_neigh_vid *softif_neigh_vid;
+       struct softif_neigh *softif_neigh;
        struct hlist_node *node, *node_tmp;
+       struct bat_priv *bat_priv;
  
-       spin_lock_bh(&bat_priv->softif_neigh_lock);
+       softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu);
+       bat_priv = softif_neigh_vid->bat_priv;
  
+       spin_lock_bh(&bat_priv->softif_neigh_lock);
        hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
-                                 &bat_priv->softif_neigh_list, list) {
+                                 &softif_neigh_vid->softif_neigh_list, list) {
+               hlist_del_rcu(&softif_neigh->list);
+               softif_neigh_free_ref(softif_neigh);
+       }
+       spin_unlock_bh(&bat_priv->softif_neigh_lock);
  
-               if ((!time_after(jiffies, softif_neigh->last_seen +
-                               msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) &&
-                   (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
-                       continue;
+       kfree(softif_neigh_vid);
+ }
  
-               hlist_del_rcu(&softif_neigh->list);
+ static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid)
+ {
+       if (atomic_dec_and_test(&softif_neigh_vid->refcount))
+               call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu);
+ }
  
-               if (bat_priv->softif_neigh == softif_neigh) {
-                       bat_dbg(DBG_ROUTES, bat_priv,
-                                "Current mesh exit point '%pM' vanished "
-                                "(vid: %d).\n",
-                                softif_neigh->addr, softif_neigh->vid);
-                       softif_neigh_tmp = bat_priv->softif_neigh;
-                       bat_priv->softif_neigh = NULL;
-                       softif_neigh_free_ref(softif_neigh_tmp);
-               }
+ static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv,
+                                                    short vid)
+ {
+       struct softif_neigh_vid *softif_neigh_vid;
+       struct hlist_node *node;
  
-               softif_neigh_free_ref(softif_neigh);
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(softif_neigh_vid, node,
+                                &bat_priv->softif_neigh_vids, list) {
+               if (softif_neigh_vid->vid != vid)
+                       continue;
+ 
+               if (!atomic_inc_not_zero(&softif_neigh_vid->refcount))
+                       continue;
+ 
+               goto out;
        }
  
-       spin_unlock_bh(&bat_priv->softif_neigh_lock);
+       softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid),
+                                  GFP_ATOMIC);
+       if (!softif_neigh_vid)
+               goto out;
+ 
+       softif_neigh_vid->vid = vid;
+       softif_neigh_vid->bat_priv = bat_priv;
+ 
+       /* initialize with 2 - caller decrements counter by one */
+       atomic_set(&softif_neigh_vid->refcount, 2);
+       INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list);
+       INIT_HLIST_NODE(&softif_neigh_vid->list);
+       spin_lock_bh(&bat_priv->softif_neigh_vid_lock);
+       hlist_add_head_rcu(&softif_neigh_vid->list,
+                          &bat_priv->softif_neigh_vids);
+       spin_unlock_bh(&bat_priv->softif_neigh_vid_lock);
+ 
+ out:
+       rcu_read_unlock();
+       return softif_neigh_vid;
  }
  
  static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
 
        ieee80211_tx_skb(sdata, skb);
  }
  
 -static void kfree_tid_tx(struct rcu_head *rcu_head)
 -{
 -      struct tid_ampdu_tx *tid_tx =
 -          container_of(rcu_head, struct tid_ampdu_tx, rcu_head);
 -
 -      kfree(tid_tx);
 -}
 -
+ void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
+                            struct tid_ampdu_tx *tid_tx)
+ {
+       lockdep_assert_held(&sta->ampdu_mlme.mtx);
+       lockdep_assert_held(&sta->lock);
+       rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
+ }
+ 
  int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                                    enum ieee80211_back_parties initiator,
                                    bool tx)
  
        lockdep_assert_held(&sta->ampdu_mlme.mtx);
  
-       if (!tid_tx)
-               return -ENOENT;
- 
        spin_lock_bh(&sta->lock);
  
+       tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+       if (!tid_tx) {
+               spin_unlock_bh(&sta->lock);
+               return -ENOENT;
+       }
+ 
        if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /* not even started yet! */
-               rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
+               ieee80211_assign_tid_tx(sta, tid, NULL);
                spin_unlock_bh(&sta->lock);
 -              call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
 +              kfree_rcu(tid_tx, rcu_head);
                return 0;
        }