aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch')
-rw-r--r--package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch191
1 files changed, 191 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch b/package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch
new file mode 100644
index 0000000000..f4e4b8b075
--- /dev/null
+++ b/package/kernel/mac80211/patches/020-14-rt2x00-use-txdone_nomatch-on-rt2800usb.patch
@@ -0,0 +1,191 @@
+From 293dff78ee058ec1e0b90e05a803c512b6a2097f Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Wed, 15 Feb 2017 10:25:10 +0100
+Subject: [PATCH 14/19] rt2x00: use txdone_nomatch on rt2800usb
+
+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 | 31 ++++++++++++++++++++-----
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 3 ++-
+ drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 2 +-
+ drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 18 ++++++--------
+ 4 files changed, 35 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+index 46405cce35e0..4a7bec708a13 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -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);
+
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+index 6811d677a6e7..d9ef260d542a 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+@@ -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);
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+index de4790b41be7..3ab3b5323897 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -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;
+ }
+
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+index 205a7b8ac8a7..f11e3f532a84 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+@@ -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);
+ }
+ }
+
+--
+2.12.1
+