rt2800: status based rate flags for nomatch case
authorStanislaw Gruszka <sgruszka@redhat.com>
Wed, 15 Feb 2017 09:25:11 +0000 (10:25 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 8 Mar 2017 15:05:53 +0000 (17:05 +0200)
We use skb_desc->tx_rate_flags from entry as rate[].flags even if
skb does not match status. Patch corrects flags and also fixes
mcs for legacy rates.

rt2800_rate_from_status() is based on Felix's mt76
mt76x2_mac_process_tx_rate() function.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ralink/rt2x00/rt2800.h
drivers/net/wireless/ralink/rt2x00/rt2800lib.c

index 0e7051d8132f8743bf3b117c9a964056b6b70c9f..480b08601785050f9bfbdfb83cf11e93a996bb62 100644 (file)
 #define TX_STA_FIFO_WCID               FIELD32(0x0000ff00)
 #define TX_STA_FIFO_SUCCESS_RATE       FIELD32(0xffff0000)
 #define TX_STA_FIFO_MCS                        FIELD32(0x007f0000)
+#define TX_STA_FIFO_BW                 FIELD32(0x00800000)
+#define TX_STA_FIFO_SGI                        FIELD32(0x01000000)
 #define TX_STA_FIFO_PHYMODE            FIELD32(0xc0000000)
 
 /*
index 4a7bec708a13dc1c85a22ad5097d8603bd679fda..8d00c599e47ac0eb61f1b4a6f5d4d180a7ae7511 100644 (file)
@@ -852,6 +852,39 @@ void rt2800_process_rxwi(struct queue_entry *entry,
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
+static void rt2800_rate_from_status(struct skb_frame_desc *skbdesc,
+                                   u32 status, enum nl80211_band band)
+{
+       u8 flags = 0;
+       u8 idx = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
+
+       switch (rt2x00_get_field32(status, TX_STA_FIFO_PHYMODE)) {
+       case RATE_MODE_HT_GREENFIELD:
+               flags |= IEEE80211_TX_RC_GREEN_FIELD;
+               /* fall through */
+       case RATE_MODE_HT_MIX:
+               flags |= IEEE80211_TX_RC_MCS;
+               break;
+       case RATE_MODE_OFDM:
+               if (band == NL80211_BAND_2GHZ)
+                       idx += 4;
+               break;
+       case RATE_MODE_CCK:
+               if (idx >= 8)
+                       idx -= 8;
+               break;
+       }
+
+       if (rt2x00_get_field32(status, TX_STA_FIFO_BW))
+               flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+
+       if (rt2x00_get_field32(status, TX_STA_FIFO_SGI))
+               flags |= IEEE80211_TX_RC_SHORT_GI;
+
+       skbdesc->tx_rate_idx = idx;
+       skbdesc->tx_rate_flags = flags;
+}
+
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
                         bool match)
 {
@@ -898,7 +931,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
         * and provide retry count.
         */
        if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
-               skbdesc->tx_rate_idx = real_mcs;
+               rt2800_rate_from_status(skbdesc, status, rt2x00dev->curr_band);
                mcs = real_mcs;
        }