Skip to content

Commit

Permalink
rt2x00: use txdone_nomatch on rt2800usb
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
  • Loading branch information
Stanislaw Gruszka authored and Kalle Valo committed Mar 8, 2017
1 parent ec80ad7 commit 293dff7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 19 deletions.
31 changes: 25 additions & 6 deletions drivers/net/wireless/ralink/rt2x00/rt2800lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,16 +852,16 @@ 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;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
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.
Expand All @@ -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
Expand All @@ -891,15 +892,22 @@ 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;
}

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
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/ralink/rt2x00/rt2800lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
18 changes: 7 additions & 11 deletions drivers/net/wireless/ralink/rt2x00/rt2800usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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)) {
/*
Expand All @@ -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);
}
}

Expand Down

0 comments on commit 293dff7

Please sign in to comment.