rt2x00: use txdone_nomatch on rt2800usb
authorStanislaw Gruszka <sgruszka@redhat.com>
Wed, 15 Feb 2017 09:25:10 +0000 (10:25 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 8 Mar 2017 15:05:52 +0000 (17:05 +0200)
If we do not match skb entry, provide tx status via nomatch procedure.

Currently in that case we do rt2x00lib_txdone_noinfo(TXDONE_NOINFO),
which actually assume that entry->skb was posted without retries and
provide rate saved in skb desc as successful. Patch changed that to
rate read from TX_STAT_FIFO, however still do not provide correct
number of retries.

On SoC/PCI devices we keep providing status via standard txdone
procedure, no change in those devices, though we should thing about it.

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

index 46405cce35e00594035e3abb11d1c289d25d14b5..4a7bec708a13dc1c85a22ad5097d8603bd679fda 100644 (file)
@@ -852,7 +852,8 @@ void rt2800_process_rxwi(struct queue_entry *entry,
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
+                        bool match)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -860,8 +861,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
        struct txdone_entry_desc txdesc;
        u32 word;
        u16 mcs, real_mcs;
-       int aggr, ampdu;
-       int wcid;
+       int aggr, ampdu, wcid, ack_req;
 
        /*
         * Obtain the status about this packet.
@@ -875,6 +875,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
        real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
        aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
        wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
+       ack_req = rt2x00_get_field32(status, TX_STA_FIFO_TX_ACK_REQUIRED);
 
        /*
         * If a frame was meant to be sent as a single non-aggregated MPDU
@@ -891,8 +892,12 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
         * Hence, replace the requested rate with the real tx rate to not
         * confuse the rate control algortihm by providing clearly wrong
         * data.
-        */
-       if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
+        *
+        * FIXME: if we do not find matching entry, we tell that frame was
+        * posted without any retries. We need to find a way to fix that
+        * and provide retry count.
+        */
+       if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
                skbdesc->tx_rate_idx = real_mcs;
                mcs = real_mcs;
        }
@@ -900,6 +905,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
        if (aggr == 1 || ampdu == 1)
                __set_bit(TXDONE_AMPDU, &txdesc.flags);
 
+       if (!ack_req)
+               __set_bit(TXDONE_NO_ACK_REQ, &txdesc.flags);
+
        /*
         * Ralink has a retry mechanism using a global fallback
         * table. We setup this fallback table to try the immediate
@@ -931,7 +939,18 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
        if (txdesc.retry)
                __set_bit(TXDONE_FALLBACK, &txdesc.flags);
 
-       rt2x00lib_txdone(entry, &txdesc);
+       if (!match) {
+               /* RCU assures non-null sta will not be freed by mac80211. */
+               rcu_read_lock();
+               if (likely(wcid >= WCID_START && wcid <= WCID_END))
+                       skbdesc->sta = drv_data->wcid_to_sta[wcid - WCID_START];
+               else
+                       skbdesc->sta = NULL;
+               rt2x00lib_txdone_nomatch(entry, &txdesc);
+               rcu_read_unlock();
+       } else {
+               rt2x00lib_txdone(entry, &txdesc);
+       }
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
index 6811d677a6e7af6b0d9c6008abd78a2405a36573..d9ef260d542a199425f45ee1e57bd9ffaeb1eea9 100644 (file)
@@ -191,7 +191,8 @@ void rt2800_write_tx_data(struct queue_entry *entry,
                          struct txentry_desc *txdesc);
 void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
 
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
+                        bool match);
 
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
 void rt2800_clear_beacon(struct queue_entry *entry);
index de4790b41be7d64a7c3a9651e27451c3f76183d6..3ab3b53238974a72c5d2170215666e4890110d4e 100644 (file)
@@ -239,7 +239,7 @@ static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
 {
        if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
                rt2800_txdone_entry(entry, entry->status,
-                                   rt2800mmio_get_txwi(entry));
+                                   rt2800mmio_get_txwi(entry), true);
                return false;
        }
 
index 205a7b8ac8a7a252845f8e8c5866f2ed4cd1e14d..f11e3f532a84e48e17e9d530030c3f066099fe7f 100644 (file)
@@ -501,8 +501,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
 /*
  * TX control handlers
  */
-static enum txdone_entry_desc_flags
-rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
 {
        __le32 *txwi;
        u32 word;
@@ -515,7 +514,7 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
         * frame.
         */
        if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
-               return TXDONE_FAILURE;
+               return false;
 
        wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
        ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
@@ -537,10 +536,10 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
                rt2x00_dbg(entry->queue->rt2x00dev,
                           "TX status report missed for queue %d entry %d\n",
                           entry->queue->qid, entry->entry_idx);
-               return TXDONE_UNKNOWN;
+               return false;
        }
 
-       return TXDONE_SUCCESS;
+       return true;
 }
 
 static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
@@ -549,7 +548,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
        struct queue_entry *entry;
        u32 reg;
        u8 qid;
-       enum txdone_entry_desc_flags done_status;
+       bool match;
 
        while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
                /*
@@ -574,11 +573,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
                        break;
                }
 
-               done_status = rt2800usb_txdone_entry_check(entry, reg);
-               if (likely(done_status == TXDONE_SUCCESS))
-                       rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
-               else
-                       rt2x00lib_txdone_noinfo(entry, done_status);
+               match = rt2800usb_txdone_entry_check(entry, reg);
+               rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
        }
 }