diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-08-06 08:18:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-09 15:58:11 -0400 |
commit | 8fed14085595c703612b5b712ffe114ef0370929 (patch) | |
tree | cf20f55f47cffa2323b9e41ae4b4059be129951f /drivers/net/wireless/ath/ath9k | |
parent | a1cd94d345a8f68300c8ccd8422434e54199f68d (diff) |
ath9k: fix block ack window tracking check
When a packet has been tracked as part of the BlockAck window and added
to the hardware queue, it can end up back in the TID queue again with
fi->retries still set to 0 (e.g. if the frame was filtered). Keep an
extra bit for the BAW tracking status to fix this corner case.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 15 |
2 files changed, 11 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 725515fd5ffe..126f98066f1b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -211,8 +211,9 @@ struct ath_frame_info { | |||
211 | int framelen; | 211 | int framelen; |
212 | enum ath9k_key_type keytype; | 212 | enum ath9k_key_type keytype; |
213 | u8 keyix; | 213 | u8 keyix; |
214 | u8 retries; | ||
215 | u8 rtscts_rate; | 214 | u8 rtscts_rate; |
215 | u8 retries : 7; | ||
216 | u8 baw_tracked : 1; | ||
216 | }; | 217 | }; |
217 | 218 | ||
218 | struct ath_buf_state { | 219 | struct ath_buf_state { |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 887f2d4a4452..d66e8b855f85 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -225,7 +225,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
225 | } | 225 | } |
226 | } | 226 | } |
227 | 227 | ||
228 | if (fi->retries) { | 228 | if (fi->baw_tracked) { |
229 | list_add_tail(&bf->list, &bf_head); | 229 | list_add_tail(&bf->list, &bf_head); |
230 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 230 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
231 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 231 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
@@ -262,13 +262,16 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
262 | } | 262 | } |
263 | 263 | ||
264 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 264 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
265 | u16 seqno) | 265 | struct ath_buf *bf) |
266 | { | 266 | { |
267 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | ||
268 | u16 seqno = bf->bf_state.seqno; | ||
267 | int index, cindex; | 269 | int index, cindex; |
268 | 270 | ||
269 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 271 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
270 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 272 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
271 | __set_bit(cindex, tid->tx_buf); | 273 | __set_bit(cindex, tid->tx_buf); |
274 | fi->baw_tracked = 1; | ||
272 | 275 | ||
273 | if (index >= ((tid->baw_tail - tid->baw_head) & | 276 | if (index >= ((tid->baw_tail - tid->baw_head) & |
274 | (ATH_TID_MAX_BUFS - 1))) { | 277 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -960,8 +963,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
960 | bf->bf_next = NULL; | 963 | bf->bf_next = NULL; |
961 | 964 | ||
962 | /* link buffers of this frame to the aggregate */ | 965 | /* link buffers of this frame to the aggregate */ |
963 | if (!fi->retries) | 966 | if (!fi->baw_tracked) |
964 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 967 | ath_tx_addto_baw(sc, tid, bf); |
965 | bf->bf_state.ndelim = ndelim; | 968 | bf->bf_state.ndelim = ndelim; |
966 | 969 | ||
967 | __skb_unlink(skb, tid_q); | 970 | __skb_unlink(skb, tid_q); |
@@ -1479,7 +1482,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1479 | __skb_unlink(bf->bf_mpdu, tid_q); | 1482 | __skb_unlink(bf->bf_mpdu, tid_q); |
1480 | list_add_tail(&bf->list, &bf_q); | 1483 | list_add_tail(&bf->list, &bf_q); |
1481 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | 1484 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1482 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 1485 | ath_tx_addto_baw(sc, tid, bf); |
1483 | bf->bf_state.bf_type &= ~BUF_AGGR; | 1486 | bf->bf_state.bf_type &= ~BUF_AGGR; |
1484 | if (bf_tail) | 1487 | if (bf_tail) |
1485 | bf_tail->bf_next = bf; | 1488 | bf_tail->bf_next = bf; |
@@ -1912,7 +1915,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq, | |||
1912 | list_add(&bf->list, &bf_head); | 1915 | list_add(&bf->list, &bf_head); |
1913 | 1916 | ||
1914 | /* Add sub-frame to BAW */ | 1917 | /* Add sub-frame to BAW */ |
1915 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 1918 | ath_tx_addto_baw(sc, tid, bf); |
1916 | 1919 | ||
1917 | /* Queue to h/w without aggregation */ | 1920 | /* Queue to h/w without aggregation */ |
1918 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | 1921 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); |