diff options
Diffstat (limited to 'package/mac80211/patches/564-ath9k_track_last_bar.patch')
-rw-r--r-- | package/mac80211/patches/564-ath9k_track_last_bar.patch | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/package/mac80211/patches/564-ath9k_track_last_bar.patch b/package/mac80211/patches/564-ath9k_track_last_bar.patch new file mode 100644 index 0000000000..34a4dd1ddb --- /dev/null +++ b/package/mac80211/patches/564-ath9k_track_last_bar.patch @@ -0,0 +1,82 @@ +--- 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; |