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 <[email protected]>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    |  2 ++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 35 +++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h 
b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 0e7051d..480b086 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -1760,6 +1760,8 @@
 #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)
 
 /*
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 4a7bec7..8d00c59 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -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;
        }
 
-- 
1.8.3.1

Reply via email to