diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-12-14 16:08:08 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-15 14:46:36 -0500 |
commit | f94375431749d555a16659051d8033ba9a0fe83b (patch) | |
tree | 88c6c31f276a2cf974c9a0566554f7e970f22b4f /drivers/net | |
parent | 3ad2952998b08442044690fa9b4ec38c6c3fc4a9 (diff) |
ath9k: avoid retransmitting aggregation frames that a BAR was sent for
The receiver will discard them anyway.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 27 |
2 files changed, 25 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6beaff5e5be..130e5dba955 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -241,6 +241,7 @@ struct ath_atx_tid { | |||
241 | struct ath_node *an; | 241 | struct ath_node *an; |
242 | struct ath_atx_ac *ac; | 242 | struct ath_atx_ac *ac; |
243 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; | 243 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
244 | int bar_index; | ||
244 | u16 seq_start; | 245 | u16 seq_start; |
245 | u16 seq_next; | 246 | u16 seq_next; |
246 | u16 baw_size; | 247 | u16 baw_size; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 8766796b48b..23e80e63bca 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -206,6 +206,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
206 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { | 206 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
207 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 207 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
208 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 208 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
209 | if (tid->bar_index >= 0) | ||
210 | tid->bar_index--; | ||
209 | } | 211 | } |
210 | } | 212 | } |
211 | 213 | ||
@@ -263,6 +265,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
263 | 265 | ||
264 | tid->seq_next = tid->seq_start; | 266 | tid->seq_next = tid->seq_start; |
265 | tid->baw_tail = tid->baw_head; | 267 | tid->baw_tail = tid->baw_head; |
268 | tid->bar_index = -1; | ||
266 | } | 269 | } |
267 | 270 | ||
268 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 271 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
@@ -551,8 +554,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
551 | bf = bf_next; | 554 | bf = bf_next; |
552 | } | 555 | } |
553 | 556 | ||
554 | if (bar_index >= 0) | 557 | if (bar_index >= 0) { |
558 | u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index); | ||
555 | ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1)); | 559 | ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1)); |
560 | if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq)) | ||
561 | tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq); | ||
562 | } | ||
556 | 563 | ||
557 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 564 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
558 | if (!skb_queue_empty(&bf_pending)) { | 565 | if (!skb_queue_empty(&bf_pending)) { |
@@ -779,8 +786,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
779 | 786 | ||
780 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; | 787 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; |
781 | seqno = bf->bf_state.seqno; | 788 | seqno = bf->bf_state.seqno; |
782 | if (!bf_first) | ||
783 | bf_first = bf; | ||
784 | 789 | ||
785 | /* do not step over block-ack window */ | 790 | /* do not step over block-ack window */ |
786 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { | 791 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { |
@@ -788,6 +793,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
788 | break; | 793 | break; |
789 | } | 794 | } |
790 | 795 | ||
796 | if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { | ||
797 | struct ath_tx_status ts = {}; | ||
798 | struct list_head bf_head; | ||
799 | |||
800 | INIT_LIST_HEAD(&bf_head); | ||
801 | list_add(&bf->list, &bf_head); | ||
802 | __skb_unlink(skb, &tid->buf_q); | ||
803 | ath_tx_update_baw(sc, tid, seqno); | ||
804 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
805 | continue; | ||
806 | } | ||
807 | |||
808 | if (!bf_first) | ||
809 | bf_first = bf; | ||
810 | |||
791 | if (!rl) { | 811 | if (!rl) { |
792 | aggr_limit = ath_lookup_rate(sc, bf, tid); | 812 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
793 | rl = 1; | 813 | rl = 1; |
@@ -1130,6 +1150,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1130 | txtid->state |= AGGR_ADDBA_PROGRESS; | 1150 | txtid->state |= AGGR_ADDBA_PROGRESS; |
1131 | txtid->paused = true; | 1151 | txtid->paused = true; |
1132 | *ssn = txtid->seq_start = txtid->seq_next; | 1152 | *ssn = txtid->seq_start = txtid->seq_next; |
1153 | txtid->bar_index = -1; | ||
1133 | 1154 | ||
1134 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); | 1155 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); |
1135 | txtid->baw_head = txtid->baw_tail = 0; | 1156 | txtid->baw_head = txtid->baw_tail = 0; |