Merge remote branch 'wireless-next/master' into ath6kl-next
[cascardo/linux.git] / net / mac80211 / tx.c
index e05667c..782a601 100644 (file)
@@ -226,12 +226,12 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
         * have correct qos tag for some reason, due the network or the
         * peer application.
         *
-        * Note: local->uapsd_queues access is racy here. If the value is
+        * Note: ifmgd->uapsd_queues access is racy here. If the value is
         * changed via debugfs, user needs to reassociate manually to have
         * everything in sync.
         */
        if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
-           && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+           && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
            && skb_get_queue_mapping(tx->skb) == 0)
                return TX_CONTINUE;
 
@@ -448,18 +448,23 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
-       if (unlikely(!sta ||
-                    ieee80211_is_probe_resp(hdr->frame_control) ||
-                    ieee80211_is_auth(hdr->frame_control) ||
-                    ieee80211_is_assoc_resp(hdr->frame_control) ||
-                    ieee80211_is_reassoc_resp(hdr->frame_control)))
+       if (unlikely(!sta))
                return TX_CONTINUE;
 
        if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
                      test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
-                    !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) {
+                    !(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;
+               }
+
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
@@ -625,7 +630,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                         tx->local->hw.wiphy->frag_threshold);
 
        /* set up the tx rate control struct we give the RC algo */
-       txrc.hw = local_to_hw(tx->local);
+       txrc.hw = &tx->local->hw;
        txrc.sband = sband;
        txrc.bss_conf = &tx->sdata->vif.bss_conf;
        txrc.skb = tx->skb;
@@ -635,6 +640,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                txrc.max_rate_idx = -1;
        else
                txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+       memcpy(txrc.rate_idx_mcs_mask,
+              tx->sdata->rc_rateidx_mcs_mask[tx->channel->band],
+              sizeof(txrc.rate_idx_mcs_mask));
        txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
                    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
                    tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
@@ -1057,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
 {
        bool queued = false;
        bool reset_agg_timer = false;
+       struct sk_buff *purge_skb = NULL;
 
        if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
                info->flags |= IEEE80211_TX_CTL_AMPDU;
@@ -1098,8 +1107,13 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                        info->control.vif = &tx->sdata->vif;
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                        __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);
                }
                spin_unlock(&tx->sta->lock);
+
+               if (purge_skb)
+                       dev_kfree_skb(purge_skb);
        }
 
        /* reset session timer */
@@ -2203,7 +2217,8 @@ void ieee80211_tx_pending(unsigned long data)
 
 /* functions for drivers to get certain frames */
 
-static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
+static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_if_ap *bss,
                                     struct sk_buff *skb,
                                     struct beacon_data *beacon)
 {
@@ -2220,7 +2235,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
                                          IEEE80211_MAX_AID+1);
 
        if (bss->dtim_count == 0)
-               bss->dtim_count = beacon->dtim_period - 1;
+               bss->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
        else
                bss->dtim_count--;
 
@@ -2228,7 +2243,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
        *pos++ = WLAN_EID_TIM;
        *pos++ = 4;
        *pos++ = bss->dtim_count;
-       *pos++ = beacon->dtim_period;
+       *pos++ = sdata->vif.bss_conf.dtim_period;
 
        if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
                aid0 = 1;
@@ -2321,12 +2336,14 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         * of the tim bitmap in mac80211 and the driver.
                         */
                        if (local->tim_in_locked_section) {
-                               ieee80211_beacon_add_tim(ap, skb, beacon);
+                               ieee80211_beacon_add_tim(sdata, ap, skb,
+                                                        beacon);
                        } else {
                                unsigned long flags;
 
                                spin_lock_irqsave(&local->tim_lock, flags);
-                               ieee80211_beacon_add_tim(ap, skb, beacon);
+                               ieee80211_beacon_add_tim(sdata, ap, skb,
+                                                        beacon);
                                spin_unlock_irqrestore(&local->tim_lock, flags);
                        }
 
@@ -2431,6 +2448,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                txrc.max_rate_idx = -1;
        else
                txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+       memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
+              sizeof(txrc.rate_idx_mcs_mask));
        txrc.bss = true;
        rate_control_get_rate(sdata, NULL, &txrc);