Commit b34793ee authored by Helmut Schaa's avatar Helmut Schaa Committed by John W. Linville

rt2x00: Work around hw aggregation oddity in rt2800

If a frame is not meant to be sent as AMPDU or part of it the hw might
still decide to aggregate this frame if a previous frame started an
AMPDU. However, this will limit the usefulness of the reported tx rate
since the reported rate will be the one specified in the TXWI of the
first frame and thus it is not possible to reliably caculate the
number of retrys by substracting the reported tx rate from the tx rate
in the TXWI.

To fix this issue, only report the successful rate for frames that were
not meant to be aggregated but ended up in an aggregate.

Example:
Frame A (MCS7, AMPDU=1) B (MCS7, AMPDU=1) C (MCS12, AMDPU=0, PROBE_RATE)

Although frame C shoudn't be aggregated the hw might sill put it
into an AMPDU together with A and B. If the transmission succeeds the tx
status will contain MCS7 for all three frames. In that case we should
only report MCS7 as success rate and avoid reporting MCS12-MCS8 as
failed tx attempts as this will affect the future rate control
decisions.

This oddity might strike us in other scenarious as well but the most
common "wrong" report happened for frames used to probe a different tx
rate.

This improves the rate control decisions notable.
Signed-off-by: default avatarHelmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 01e946f2
...@@ -634,9 +634,11 @@ static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) ...@@ -634,9 +634,11 @@ static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
void rt2800_txdone_entry(struct queue_entry *entry, u32 status) void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
{ {
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
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;
__le32 *txwi; __le32 *txwi;
/* /*
...@@ -645,8 +647,33 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status) ...@@ -645,8 +647,33 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
txdesc.flags = 0; txdesc.flags = 0;
txwi = rt2800_drv_get_txwi(entry); txwi = rt2800_drv_get_txwi(entry);
rt2x00_desc_read(txwi, 0, &word); rt2x00_desc_read(txwi, 0, &word);
mcs = rt2x00_get_field32(word, TXWI_W0_MCS); mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
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);
/*
* If a frame was meant to be sent as a single non-aggregated MPDU
* but ended up in an aggregate the used tx rate doesn't correlate
* with the one specified in the TXWI as the whole aggregate is sent
* with the same rate.
*
* For example: two frames are sent to rt2x00, the first one sets
* AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0
* and requests MCS15. If the hw aggregates both frames into one
* AMDPU the tx status for both frames will contain MCS7 although
* the frame was sent successfully.
*
* Hence, replace the requested rate with the real tx rate to not
* confuse the rate control algortihm by providing clearly wrong
* data.
*/
if (aggr == 1 && ampdu == 0 && real_mcs != mcs) {
skbdesc->tx_rate_idx = real_mcs;
mcs = real_mcs;
}
/* /*
* Ralink has a retry mechanism using a global fallback * Ralink has a retry mechanism using a global fallback
......
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