Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[cascardo/linux.git] / net / mac80211 / tx.c
index 6d59e21..27c990b 100644 (file)
@@ -464,7 +464,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
        if (unlikely(!sta))
@@ -475,15 +474,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
-               /* only deauth, disassoc and action are bufferable MMPDUs */
-               if (ieee80211_is_mgmt(hdr->frame_control) &&
-                   !ieee80211_is_deauth(hdr->frame_control) &&
-                   !ieee80211_is_disassoc(hdr->frame_control) &&
-                   !ieee80211_is_action(hdr->frame_control)) {
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-                       return TX_CONTINUE;
-               }
-
                ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -500,6 +490,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                info->control.jiffies = jiffies;
                info->control.vif = &tx->sdata->vif;
                info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+               info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
                skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
 
                if (!timer_pending(&local->sta_cleanup))
@@ -526,9 +517,22 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
        if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
                return TX_CONTINUE;
 
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_deauth(hdr->frame_control) &&
+           !ieee80211_is_disassoc(hdr->frame_control) &&
+           !ieee80211_is_action(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+       }
+
        if (tx->flags & IEEE80211_TX_UNICAST)
                return ieee80211_tx_h_unicast_ps_buf(tx);
        else
@@ -1073,6 +1077,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                        queued = true;
                        info->control.vif = &tx->sdata->vif;
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+                       info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
                        __skb_queue_tail(&tid_tx->pending, skb);
                        if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
                                purge_skb = __skb_dequeue(&tid_tx->pending);
@@ -2161,7 +2166,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        if (ieee80211_is_data_qos(fc)) {
                __le16 *qos_control;
 
-               qos_control = (__le16*) skb_push(skb, 2);
+               qos_control = (__le16 *) skb_push(skb, 2);
                memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
                /*
                 * Maybe we could actually set some fields here, for now just
@@ -2323,7 +2328,7 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
        if (atomic_read(&ps->num_sta_ps) > 0)
                /* in the hope that this is faster than
                 * checking byte-for-byte */
-               have_bits = !bitmap_empty((unsigned long*)ps->tim,
+               have_bits = !bitmap_empty((unsigned long *)ps->tim,
                                          IEEE80211_MAX_AID+1);
 
        if (ps->dtim_count == 0)
@@ -2549,7 +2554,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         */
                        skb = dev_alloc_skb(local->tx_headroom +
                                            beacon->head_len +
-                                           beacon->tail_len + 256);
+                                           beacon->tail_len + 256 +
+                                           local->hw.extra_beacon_tailroom);
                        if (!skb)
                                goto out;
 
@@ -2581,7 +2587,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, presp);
 
 
-               skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
+               skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);
@@ -2602,13 +2609,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, bcn);
 
                if (ifmsh->sync_ops)
-                       ifmsh->sync_ops->adjust_tbtt(
-                                               sdata);
+                       ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
 
                skb = dev_alloc_skb(local->tx_headroom +
                                    bcn->head_len +
                                    256 + /* TIM IE */
-                                   bcn->tail_len);
+                                   bcn->tail_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);