diff options
Diffstat (limited to 'package/kernel/mac80211/patches/571-ath9k_tid_fairness.patch')
-rw-r--r-- | package/kernel/mac80211/patches/571-ath9k_tid_fairness.patch | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/571-ath9k_tid_fairness.patch b/package/kernel/mac80211/patches/571-ath9k_tid_fairness.patch new file mode 100644 index 0000000000..30ae0908ec --- /dev/null +++ b/package/kernel/mac80211/patches/571-ath9k_tid_fairness.patch @@ -0,0 +1,153 @@ +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -1317,8 +1317,8 @@ ath_tx_form_burst(struct ath_softc *sc, + } while (1); + } + +-static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, +- struct ath_atx_tid *tid) ++static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ++ struct ath_atx_tid *tid, bool *stop) + { + struct ath_buf *bf; + struct ieee80211_tx_info *tx_info; +@@ -1327,40 +1327,39 @@ static void ath_tx_sched_aggr(struct ath + int aggr_len = 0; + bool aggr, last = true; + +- do { +- if (!ath_tid_has_buffered(tid)) +- return; +- +- INIT_LIST_HEAD(&bf_q); +- +- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); +- if (!bf) +- break; ++ if (!ath_tid_has_buffered(tid)) ++ return false; + +- tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); +- aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); +- if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || +- (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) +- break; ++ INIT_LIST_HEAD(&bf_q); + +- ath_set_rates(tid->an->vif, tid->an->sta, bf); +- if (aggr) +- last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, +- tid_q, &aggr_len); +- else +- ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); ++ bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); ++ if (!bf) ++ return false; ++ ++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); ++ aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); ++ if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || ++ (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) ++ return false; ++ ++ ath_set_rates(tid->an->vif, tid->an->sta, bf); ++ if (aggr) ++ last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, ++ tid_q, &aggr_len); ++ else ++ ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); + +- if (list_empty(&bf_q)) +- return; ++ if (list_empty(&bf_q)) ++ return false; + +- if (tid->ac->clear_ps_filter) { +- tid->ac->clear_ps_filter = false; +- tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; +- } ++ if (tid->ac->clear_ps_filter) { ++ tid->ac->clear_ps_filter = false; ++ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; ++ } + +- ath_tx_fill_desc(sc, bf, txq, aggr_len); +- ath_tx_txqaddbuf(sc, txq, &bf_q, false); +- } while (!last); ++ ath_tx_fill_desc(sc, bf, txq, aggr_len); ++ ath_tx_txqaddbuf(sc, txq, &bf_q, false); ++ return true; + } + + int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, +@@ -1796,8 +1795,9 @@ void ath_tx_cleanupq(struct ath_softc *s + */ + void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) + { +- struct ath_atx_ac *ac, *ac_tmp, *last_ac; ++ struct ath_atx_ac *ac, *last_ac; + struct ath_atx_tid *tid, *last_tid; ++ bool sent = false; + + if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || + list_empty(&txq->axq_acq) || +@@ -1806,15 +1806,17 @@ void ath_txq_schedule(struct ath_softc * + + rcu_read_lock(); + +- ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); + last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); ++ while (!list_empty(&txq->axq_acq)) { ++ bool stop = false; + +- list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { ++ ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); + last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); + list_del(&ac->list); + ac->sched = false; + + while (!list_empty(&ac->tid_q)) { ++ + tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, + list); + list_del(&tid->list); +@@ -1823,7 +1825,8 @@ void ath_txq_schedule(struct ath_softc * + if (tid->paused) + continue; + +- ath_tx_sched_aggr(sc, txq, tid); ++ if (ath_tx_sched_aggr(sc, txq, tid, &stop)) ++ sent = true; + + /* + * add tid to round-robin queue if more frames +@@ -1832,8 +1835,7 @@ void ath_txq_schedule(struct ath_softc * + if (ath_tid_has_buffered(tid)) + ath_tx_queue_tid(txq, tid); + +- if (tid == last_tid || +- txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ++ if (stop || tid == last_tid) + break; + } + +@@ -1842,9 +1844,17 @@ void ath_txq_schedule(struct ath_softc * + list_add_tail(&ac->list, &txq->axq_acq); + } + +- if (ac == last_ac || +- txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ++ if (stop) + break; ++ ++ if (ac == last_ac) { ++ if (!sent) ++ break; ++ ++ sent = false; ++ last_ac = list_entry(txq->axq_acq.prev, ++ struct ath_atx_ac, list); ++ } + } + + rcu_read_unlock(); |