Merge tag 'please-pull-fixmcelog' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / net / mac80211 / status.c
index bb146f3..e679b7c 100644 (file)
@@ -664,13 +664,15 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
        struct ieee80211_supported_band *sband;
        int retry_count;
        int rates_idx;
-       bool acked;
+       bool acked, noack_success;
 
        rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
 
        sband = hw->wiphy->bands[info->band];
 
        acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
+       noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
+
        if (pubsta) {
                struct sta_info *sta;
 
@@ -696,7 +698,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
                rate_control_tx_status_noskb(local, sband, sta, info);
        }
 
-       if (acked) {
+       if (acked || noack_success) {
                    local->dot11TransmittedFrameCount++;
                    if (!pubsta)
                            local->dot11MulticastTransmittedFrameCount++;
@@ -728,6 +730,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ieee80211_bar *bar;
        int rtap_len;
        int shift = 0;
+       int tid = IEEE80211_NUM_TIDS;
 
        rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
 
@@ -771,7 +774,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 
                if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
                    (ieee80211_is_data_qos(fc))) {
-                       u16 tid, ssn;
+                       u16 ssn;
                        u8 *qc;
 
                        qc = ieee80211_get_qos_ctl(hdr);
@@ -780,10 +783,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                                                & IEEE80211_SCTL_SEQ);
                        ieee80211_send_bar(&sta->sdata->vif, hdr->addr1,
                                           tid, ssn);
+               } else if (ieee80211_is_data_qos(fc)) {
+                       u8 *qc = ieee80211_get_qos_ctl(hdr);
+
+                       tid = qc[0] & 0xf;
                }
 
                if (!acked && ieee80211_is_back_req(fc)) {
-                       u16 tid, control;
+                       u16 control;
 
                        /*
                         * BAR failed, store the last SSN and retry sending
@@ -811,6 +818,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                        if (!acked)
                                sta->tx_retry_failed++;
                        sta->tx_retry_count += retry_count;
+
+                       if (ieee80211_is_data_present(fc)) {
+                               if (!acked)
+                                       sta->tx_msdu_failed[tid]++;
+                               sta->tx_msdu_retries[tid] += retry_count;
+                       }
                }
 
                rate_control_tx_status(local, sband, sta, skb);
@@ -856,10 +869,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
         * Fragments are passed to low-level drivers as separate skbs, so these
         * are actually fragments, not frames. Update frame counters only for
         * the first fragment of the frame. */
-       if (info->flags & IEEE80211_TX_STAT_ACK) {
+       if ((info->flags & IEEE80211_TX_STAT_ACK) ||
+           (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) {
                if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
                        local->dot11TransmittedFrameCount++;
-                       if (is_multicast_ether_addr(hdr->addr1))
+                       if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
                                local->dot11MulticastTransmittedFrameCount++;
                        if (retry_count > 0)
                                local->dot11RetryCount++;