Commit 293dff78 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by Kalle Valo

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: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent ec80ad70
...@@ -852,7 +852,8 @@ void rt2800_process_rxwi(struct queue_entry *entry, ...@@ -852,7 +852,8 @@ void rt2800_process_rxwi(struct queue_entry *entry,
} }
EXPORT_SYMBOL_GPL(rt2800_process_rxwi); 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 rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; 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) ...@@ -860,8 +861,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
struct txdone_entry_desc txdesc; struct txdone_entry_desc txdesc;
u32 word; u32 word;
u16 mcs, real_mcs; u16 mcs, real_mcs;
int aggr, ampdu; int aggr, ampdu, wcid, ack_req;
int wcid;
/* /*
* Obtain the status about this packet. * Obtain the status about this packet.
...@@ -875,6 +875,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi) ...@@ -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); real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE); aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); 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 * 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) ...@@ -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 * Hence, replace the requested rate with the real tx rate to not
* confuse the rate control algortihm by providing clearly wrong * confuse the rate control algortihm by providing clearly wrong
* data. * data.
*
* 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)) { if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
skbdesc->tx_rate_idx = real_mcs; skbdesc->tx_rate_idx = real_mcs;
mcs = real_mcs; mcs = real_mcs;
} }
...@@ -900,6 +905,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi) ...@@ -900,6 +905,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
if (aggr == 1 || ampdu == 1) if (aggr == 1 || ampdu == 1)
__set_bit(TXDONE_AMPDU, &txdesc.flags); __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 * Ralink has a retry mechanism using a global fallback
* table. We setup this fallback table to try the immediate * 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) ...@@ -931,7 +939,18 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
if (txdesc.retry) if (txdesc.retry)
__set_bit(TXDONE_FALLBACK, &txdesc.flags); __set_bit(TXDONE_FALLBACK, &txdesc.flags);
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); rt2x00lib_txdone(entry, &txdesc);
}
} }
EXPORT_SYMBOL_GPL(rt2800_txdone_entry); EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
......
...@@ -191,7 +191,8 @@ void rt2800_write_tx_data(struct queue_entry *entry, ...@@ -191,7 +191,8 @@ void rt2800_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc); struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_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_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry); void rt2800_clear_beacon(struct queue_entry *entry);
......
...@@ -239,7 +239,7 @@ static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry, ...@@ -239,7 +239,7 @@ static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
{ {
if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
rt2800_txdone_entry(entry, entry->status, rt2800_txdone_entry(entry, entry->status,
rt2800mmio_get_txwi(entry)); rt2800mmio_get_txwi(entry), true);
return false; return false;
} }
......
...@@ -501,8 +501,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) ...@@ -501,8 +501,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/* /*
* TX control handlers * TX control handlers
*/ */
static enum txdone_entry_desc_flags static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
{ {
__le32 *txwi; __le32 *txwi;
u32 word; u32 word;
...@@ -515,7 +514,7 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg) ...@@ -515,7 +514,7 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
* frame. * frame.
*/ */
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
return TXDONE_FAILURE; return false;
wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); 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) ...@@ -537,10 +536,10 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
rt2x00_dbg(entry->queue->rt2x00dev, rt2x00_dbg(entry->queue->rt2x00dev,
"TX status report missed for queue %d entry %d\n", "TX status report missed for queue %d entry %d\n",
entry->queue->qid, entry->entry_idx); entry->queue->qid, entry->entry_idx);
return TXDONE_UNKNOWN; return false;
} }
return TXDONE_SUCCESS; return true;
} }
static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
...@@ -549,7 +548,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) ...@@ -549,7 +548,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
struct queue_entry *entry; struct queue_entry *entry;
u32 reg; u32 reg;
u8 qid; u8 qid;
enum txdone_entry_desc_flags done_status; bool match;
while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) { while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
/* /*
...@@ -574,11 +573,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) ...@@ -574,11 +573,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
break; break;
} }
done_status = rt2800usb_txdone_entry_check(entry, reg); match = rt2800usb_txdone_entry_check(entry, reg);
if (likely(done_status == TXDONE_SUCCESS)) rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
else
rt2x00lib_txdone_noinfo(entry, done_status);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment