ath9k: add some more fixes for the tx queueing rework
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 571-ath9k_tid_fairness.patch
1 --- a/drivers/net/wireless/ath/ath9k/xmit.c
2 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
3 @@ -1317,8 +1317,8 @@ ath_tx_form_burst(struct ath_softc *sc,
4 } while (1);
5 }
6
7 -static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
8 - struct ath_atx_tid *tid)
9 +static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
10 + struct ath_atx_tid *tid, bool *stop)
11 {
12 struct ath_buf *bf;
13 struct ieee80211_tx_info *tx_info;
14 @@ -1327,40 +1327,41 @@ static void ath_tx_sched_aggr(struct ath
15 int aggr_len = 0;
16 bool aggr, last = true;
17
18 - do {
19 - if (!ath_tid_has_buffered(tid))
20 - return;
21 -
22 - INIT_LIST_HEAD(&bf_q);
23 -
24 - bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
25 - if (!bf)
26 - break;
27 + if (!ath_tid_has_buffered(tid))
28 + return false;
29
30 - tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
31 - aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
32 - if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
33 - (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH))
34 - break;
35 + INIT_LIST_HEAD(&bf_q);
36
37 - ath_set_rates(tid->an->vif, tid->an->sta, bf);
38 - if (aggr)
39 - last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
40 - tid_q, &aggr_len);
41 - else
42 - ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
43 + bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
44 + if (!bf)
45 + return false;
46 +
47 + tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
48 + aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
49 + if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
50 + (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
51 + *stop = true;
52 + return false;
53 + }
54 +
55 + ath_set_rates(tid->an->vif, tid->an->sta, bf);
56 + if (aggr)
57 + last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
58 + tid_q, &aggr_len);
59 + else
60 + ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
61
62 - if (list_empty(&bf_q))
63 - return;
64 + if (list_empty(&bf_q))
65 + return false;
66
67 - if (tid->ac->clear_ps_filter) {
68 - tid->ac->clear_ps_filter = false;
69 - tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
70 - }
71 + if (tid->ac->clear_ps_filter) {
72 + tid->ac->clear_ps_filter = false;
73 + tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
74 + }
75
76 - ath_tx_fill_desc(sc, bf, txq, aggr_len);
77 - ath_tx_txqaddbuf(sc, txq, &bf_q, false);
78 - } while (!last);
79 + ath_tx_fill_desc(sc, bf, txq, aggr_len);
80 + ath_tx_txqaddbuf(sc, txq, &bf_q, false);
81 + return true;
82 }
83
84 int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
85 @@ -1796,25 +1797,27 @@ void ath_tx_cleanupq(struct ath_softc *s
86 */
87 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
88 {
89 - struct ath_atx_ac *ac, *ac_tmp, *last_ac;
90 + struct ath_atx_ac *ac, *last_ac;
91 struct ath_atx_tid *tid, *last_tid;
92 + bool sent = false;
93
94 if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) ||
95 - list_empty(&txq->axq_acq) ||
96 - txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
97 + list_empty(&txq->axq_acq))
98 return;
99
100 rcu_read_lock();
101
102 - ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
103 last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
104 + while (!list_empty(&txq->axq_acq)) {
105 + bool stop = false;
106
107 - list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
108 + ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
109 last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
110 list_del(&ac->list);
111 ac->sched = false;
112
113 while (!list_empty(&ac->tid_q)) {
114 +
115 tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
116 list);
117 list_del(&tid->list);
118 @@ -1823,7 +1826,8 @@ void ath_txq_schedule(struct ath_softc *
119 if (tid->paused)
120 continue;
121
122 - ath_tx_sched_aggr(sc, txq, tid);
123 + if (ath_tx_sched_aggr(sc, txq, tid, &stop))
124 + sent = true;
125
126 /*
127 * add tid to round-robin queue if more frames
128 @@ -1832,8 +1836,7 @@ void ath_txq_schedule(struct ath_softc *
129 if (ath_tid_has_buffered(tid))
130 ath_tx_queue_tid(txq, tid);
131
132 - if (tid == last_tid ||
133 - txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
134 + if (stop || tid == last_tid)
135 break;
136 }
137
138 @@ -1842,9 +1845,17 @@ void ath_txq_schedule(struct ath_softc *
139 list_add_tail(&ac->list, &txq->axq_acq);
140 }
141
142 - if (ac == last_ac ||
143 - txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
144 + if (stop)
145 break;
146 +
147 + if (ac == last_ac) {
148 + if (!sent)
149 + break;
150 +
151 + sent = false;
152 + last_ac = list_entry(txq->axq_acq.prev,
153 + struct ath_atx_ac, list);
154 + }
155 }
156
157 rcu_read_unlock();