diff options
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.patch | 191 |
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, ®)) { + /* +@@ -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 + |