83 lines
2.5 KiB
Diff
83 lines
2.5 KiB
Diff
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||
|
@@ -242,6 +242,7 @@ struct ath_atx_tid {
|
||
|
struct ath_atx_ac *ac;
|
||
|
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
|
||
|
int buf_pending;
|
||
|
+ int bar_index;
|
||
|
u16 seq_start;
|
||
|
u16 seq_next;
|
||
|
u16 baw_size;
|
||
|
--- 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
|
||
|
while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
|
||
|
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
|
||
|
INCR(tid->baw_head, ATH_TID_MAX_BUFS);
|
||
|
+ if (tid->bar_index >= 0)
|
||
|
+ tid->bar_index--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -263,6 +265,7 @@ static void ath_tid_drain(struct ath_sof
|
||
|
|
||
|
tid->seq_next = tid->seq_start;
|
||
|
tid->baw_tail = tid->baw_head;
|
||
|
+ tid->bar_index = -1;
|
||
|
}
|
||
|
|
||
|
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
|
||
|
@@ -561,8 +564,12 @@ static void ath_tx_complete_aggr(struct
|
||
|
bf = bf_next;
|
||
|
}
|
||
|
|
||
|
- if (bar_index >= 0)
|
||
|
+ if (bar_index >= 0) {
|
||
|
+ u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
|
||
|
ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
|
||
|
+ if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
|
||
|
+ tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
|
||
|
+ }
|
||
|
|
||
|
/* prepend un-acked frames to the beginning of the pending frame queue */
|
||
|
if (!skb_queue_empty(&bf_pending)) {
|
||
|
@@ -789,8 +796,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_
|
||
|
|
||
|
bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
|
||
|
seqno = bf->bf_state.seqno;
|
||
|
- if (!bf_first)
|
||
|
- bf_first = bf;
|
||
|
|
||
|
/* do not step over block-ack window */
|
||
|
if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
|
||
|
@@ -798,6 +803,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
+ if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
|
||
|
+ struct ath_tx_status ts = {};
|
||
|
+ struct list_head bf_head;
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&bf_head);
|
||
|
+ list_add(&bf->list, &bf_head);
|
||
|
+ __skb_unlink(skb, &tid->buf_q);
|
||
|
+ ath_tx_update_baw(sc, tid, seqno);
|
||
|
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!bf_first)
|
||
|
+ bf_first = bf;
|
||
|
+
|
||
|
if (!rl) {
|
||
|
aggr_limit = ath_lookup_rate(sc, bf, tid);
|
||
|
rl = 1;
|
||
|
@@ -1141,6 +1161,7 @@ int ath_tx_aggr_start(struct ath_softc *
|
||
|
txtid->state |= AGGR_ADDBA_PROGRESS;
|
||
|
txtid->paused = true;
|
||
|
*ssn = txtid->seq_start = txtid->seq_next;
|
||
|
+ txtid->bar_index = -1;
|
||
|
|
||
|
memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
|
||
|
txtid->baw_head = txtid->baw_tail = 0;
|