udp6: Fix udp fragmentation for tunnel traffic.
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / sta_info.c
index 238a0cca320e621dad86cbca1830e4867459cb6d..11216bc13b27565a4734638014ad01f5d2d88911 100644 (file)
@@ -342,6 +342,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
        INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
        mutex_init(&sta->ampdu_mlme.mtx);
+#ifdef CONFIG_MAC80211_MESH
+       if (ieee80211_vif_is_mesh(&sdata->vif) &&
+           !sdata->u.mesh.user_mpm)
+               init_timer(&sta->plink_timer);
+#endif
 
        memcpy(sta->sta.addr, addr, ETH_ALEN);
        sta->local = local;
@@ -551,6 +556,15 @@ static inline void __bss_tim_clear(u8 *tim, u16 id)
        tim[id / 8] &= ~(1 << (id % 8));
 }
 
+static inline bool __bss_tim_get(u8 *tim, u16 id)
+{
+       /*
+        * This format has been mandated by the IEEE specifications,
+        * so this line may not be changed to use the test_bit() format.
+        */
+       return tim[id / 8] & (1 << (id % 8));
+}
+
 static unsigned long ieee80211_tids_for_ac(int ac)
 {
        /* If we ever support TIDs > 7, this obviously needs to be adjusted */
@@ -631,6 +645,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
  done:
        spin_lock_bh(&local->tim_lock);
 
+       if (indicate_tim == __bss_tim_get(ps->tim, id))
+               goto out_unlock;
+
        if (indicate_tim)
                __bss_tim_set(ps->tim, id);
        else
@@ -642,6 +659,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
                local->tim_in_locked_section = false;
        }
 
+out_unlock:
        spin_unlock_bh(&local->tim_lock);
 }
 
@@ -765,8 +783,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
-       int ret, i;
-       bool have_key = false;
+       int ret;
 
        might_sleep();
 
@@ -793,19 +810,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 
        list_del_rcu(&sta->list);
 
-       mutex_lock(&local->key_mtx);
-       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-               __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
-               have_key = true;
-       }
-       if (sta->ptk) {
-               __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
-               have_key = true;
-       }
-       mutex_unlock(&local->key_mtx);
-
-       if (!have_key)
-               synchronize_net();
+       /* this always calls synchronize_net() */
+       ieee80211_free_sta_keys(local, sta);
 
        sta->dead = true;
 
@@ -1391,30 +1397,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_sta_block_awake);
 
-void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta)
+void ieee80211_sta_eosp(struct ieee80211_sta *pubsta)
 {
        struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
        struct ieee80211_local *local = sta->local;
-       struct sk_buff *skb;
-       struct skb_eosp_msg_data *data;
 
        trace_api_eosp(local, pubsta);
 
-       skb = alloc_skb(0, GFP_ATOMIC);
-       if (!skb) {
-               /* too bad ... but race is better than loss */
-               clear_sta_flag(sta, WLAN_STA_SP);
-               return;
-       }
-
-       data = (void *)skb->cb;
-       memcpy(data->sta, pubsta->addr, ETH_ALEN);
-       memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN);
-       skb->pkt_type = IEEE80211_EOSP_MSG;
-       skb_queue_tail(&local->skb_queue, skb);
-       tasklet_schedule(&local->tasklet);
+       clear_sta_flag(sta, WLAN_STA_SP);
 }
-EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe);
+EXPORT_SYMBOL(ieee80211_sta_eosp);
 
 void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
                                u8 tid, bool buffered)