123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- From 5c656c71b1bf5611ce8262bab338104e04d10b8d Mon Sep 17 00:00:00 2001
- From: Stanislaw Gruszka <[email protected]>
- Date: Wed, 26 Sep 2018 12:24:53 +0200
- Subject: [PATCH 02/28] rt2800: move usb specific txdone/txstatus routines to
- rt2800lib
- In order to reuse usb txdone/txstatus routines for mmio, move them
- to common rt2800lib.c file.
- Signed-off-by: Stanislaw Gruszka <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- ---
- .../net/wireless/ralink/rt2x00/rt2800lib.c | 138 +++++++++++++++++
- .../net/wireless/ralink/rt2x00/rt2800lib.h | 3 +
- .../net/wireless/ralink/rt2x00/rt2800usb.c | 143 +-----------------
- 3 files changed, 145 insertions(+), 139 deletions(-)
- --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
- +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
- @@ -957,6 +957,47 @@ static void rt2800_rate_from_status(stru
- skbdesc->tx_rate_flags = flags;
- }
-
- +static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
- +{
- + __le32 *txwi;
- + u32 word;
- + int wcid, ack, pid;
- + int tx_wcid, tx_ack, tx_pid, is_agg;
- +
- + /*
- + * This frames has returned with an IO error,
- + * so the status report is not intended for this
- + * frame.
- + */
- + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
- + return false;
- +
- + wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- + ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
- + is_agg = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
- +
- + /*
- + * Validate if this TX status report is intended for
- + * this entry by comparing the WCID/ACK/PID fields.
- + */
- + txwi = rt2800_drv_get_txwi(entry);
- +
- + word = rt2x00_desc_read(txwi, 1);
- + tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- + tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- + tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
- +
- + if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
- + rt2x00_dbg(entry->queue->rt2x00dev,
- + "TX status report missed for queue %d entry %d\n",
- + entry->queue->qid, entry->entry_idx);
- + return false;
- + }
- +
- + return true;
- +}
- +
- void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
- bool match)
- {
- @@ -1059,6 +1100,103 @@ void rt2800_txdone_entry(struct queue_en
- }
- EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
-
- +void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
- +{
- + struct data_queue *queue;
- + struct queue_entry *entry;
- + u32 reg;
- + u8 qid;
- + bool match;
- +
- + while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
- + /*
- + * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
- + * guaranteed to be one of the TX QIDs .
- + */
- + qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- + queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- +
- + if (unlikely(rt2x00queue_empty(queue))) {
- + rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
- + qid);
- + break;
- + }
- +
- + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- +
- + if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- + rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
- + entry->entry_idx, qid);
- + break;
- + }
- +
- + match = rt2800_txdone_entry_check(entry, reg);
- + rt2800_txdone_entry(entry, reg, rt2800_drv_get_txwi(entry), match);
- + }
- +}
- +EXPORT_SYMBOL_GPL(rt2800_txdone);
- +
- +static inline bool rt2800_entry_txstatus_timeout(struct queue_entry *entry)
- +{
- + bool tout;
- +
- + if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- + return false;
- +
- + tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
- + if (unlikely(tout))
- + rt2x00_dbg(entry->queue->rt2x00dev,
- + "TX status timeout for entry %d in queue %d\n",
- + entry->entry_idx, entry->queue->qid);
- + return tout;
- +
- +}
- +
- +bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
- +{
- + struct data_queue *queue;
- + struct queue_entry *entry;
- +
- + tx_queue_for_each(rt2x00dev, queue) {
- + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- + if (rt2800_entry_txstatus_timeout(entry))
- + return true;
- + }
- + return false;
- +}
- +EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
- +
- +void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
- +{
- + struct data_queue *queue;
- + struct queue_entry *entry;
- +
- + /*
- + * Process any trailing TX status reports for IO failures,
- + * we loop until we find the first non-IO error entry. This
- + * can either be a frame which is free, is being uploaded,
- + * or has completed the upload but didn't have an entry
- + * in the TX_STAT_FIFO register yet.
- + */
- + tx_queue_for_each(rt2x00dev, queue) {
- + while (!rt2x00queue_empty(queue)) {
- + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- +
- + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- + break;
- +
- + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
- + rt2800_entry_txstatus_timeout(entry))
- + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
- + else
- + break;
- + }
- + }
- +}
- +EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
- +
- static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
- unsigned int index)
- {
- --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
- +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
- @@ -195,6 +195,9 @@ void rt2800_process_rxwi(struct queue_en
-
- void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
- bool match);
- +void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
- +void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
- +bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
-
- void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
- void rt2800_clear_beacon(struct queue_entry *entry);
- --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
- +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
- @@ -116,35 +116,6 @@ static bool rt2800usb_txstatus_pending(s
- return false;
- }
-
- -static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
- -{
- - bool tout;
- -
- - if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- - return false;
- -
- - tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
- - if (unlikely(tout))
- - rt2x00_dbg(entry->queue->rt2x00dev,
- - "TX status timeout for entry %d in queue %d\n",
- - entry->entry_idx, entry->queue->qid);
- - return tout;
- -
- -}
- -
- -static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
- -{
- - struct data_queue *queue;
- - struct queue_entry *entry;
- -
- - tx_queue_for_each(rt2x00dev, queue) {
- - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- - if (rt2800usb_entry_txstatus_timeout(entry))
- - return true;
- - }
- - return false;
- -}
- -
- #define TXSTATUS_READ_INTERVAL 1000000
-
- static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
- @@ -171,7 +142,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
- }
-
- /* Check if there is any entry that timedout waiting on TX status */
- - if (rt2800usb_txstatus_timeout(rt2x00dev))
- + if (rt2800_txstatus_timeout(rt2x00dev))
- queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-
- if (rt2800usb_txstatus_pending(rt2x00dev)) {
- @@ -501,123 +472,17 @@ static int rt2800usb_get_tx_data_len(str
- /*
- * TX control handlers
- */
- -static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
- -{
- - __le32 *txwi;
- - u32 word;
- - int wcid, ack, pid;
- - int tx_wcid, tx_ack, tx_pid, is_agg;
- -
- - /*
- - * This frames has returned with an IO error,
- - * so the status report is not intended for this
- - * frame.
- - */
- - if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
- - return false;
- -
- - wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- - ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- - pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
- - is_agg = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
- -
- - /*
- - * Validate if this TX status report is intended for
- - * this entry by comparing the WCID/ACK/PID fields.
- - */
- - txwi = rt2800usb_get_txwi(entry);
- -
- - word = rt2x00_desc_read(txwi, 1);
- - tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- - tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- - tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
- -
- - if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
- - rt2x00_dbg(entry->queue->rt2x00dev,
- - "TX status report missed for queue %d entry %d\n",
- - entry->queue->qid, entry->entry_idx);
- - return false;
- - }
- -
- - return true;
- -}
- -
- -static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
- -{
- - struct data_queue *queue;
- - struct queue_entry *entry;
- - u32 reg;
- - u8 qid;
- - bool match;
- -
- - while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
- - /*
- - * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
- - * guaranteed to be one of the TX QIDs .
- - */
- - qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- - queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
- -
- - if (unlikely(rt2x00queue_empty(queue))) {
- - rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
- - qid);
- - break;
- - }
- -
- - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- -
- - if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- - !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- - rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
- - entry->entry_idx, qid);
- - break;
- - }
- -
- - match = rt2800usb_txdone_entry_check(entry, reg);
- - rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
- - }
- -}
- -
- -static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
- -{
- - struct data_queue *queue;
- - struct queue_entry *entry;
- -
- - /*
- - * Process any trailing TX status reports for IO failures,
- - * we loop until we find the first non-IO error entry. This
- - * can either be a frame which is free, is being uploaded,
- - * or has completed the upload but didn't have an entry
- - * in the TX_STAT_FIFO register yet.
- - */
- - tx_queue_for_each(rt2x00dev, queue) {
- - while (!rt2x00queue_empty(queue)) {
- - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- -
- - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- - !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- - break;
- -
- - if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
- - rt2800usb_entry_txstatus_timeout(entry))
- - rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
- - else
- - break;
- - }
- - }
- -}
- -
- static void rt2800usb_work_txdone(struct work_struct *work)
- {
- struct rt2x00_dev *rt2x00dev =
- container_of(work, struct rt2x00_dev, txdone_work);
-
- while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
- - rt2800usb_txstatus_timeout(rt2x00dev)) {
- + rt2800_txstatus_timeout(rt2x00dev)) {
-
- - rt2800usb_txdone(rt2x00dev);
- + rt2800_txdone(rt2x00dev);
-
- - rt2800usb_txdone_nostatus(rt2x00dev);
- + rt2800_txdone_nostatus(rt2x00dev);
-
- /*
- * The hw may delay sending the packet after DMA complete
|