10c6573b8c1ff83196c19bdee4b2eafd1ff06e8e
[librecmc/librecmc.git] / package / kernel / mac80211 / patches / 344-ath9k-Introduce-airtime-fairness-scheduling-between-.patch
1 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
2 Date: Mon, 5 Dec 2016 13:27:37 +0200
3 Subject: [PATCH] ath9k: Introduce airtime fairness scheduling between stations
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 This reworks the ath9k driver to schedule transmissions to connected
9 stations in a way that enforces airtime fairness between them. It
10 accomplishes this by measuring the time spent transmitting to or
11 receiving from a station at TX and RX completion, and accounting this to
12 a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
13 deficit scheduler is employed at packet dequeue time, to control which
14 station gets the next transmission opportunity.
15
16 Airtime fairness can significantly improve the efficiency of the network
17 when station rates vary. The following throughput values are from a
18 simple three-station test scenario, where two stations operate at the
19 highest HT20 rate, and one station at the lowest, and the scheduler is
20 employed at the access point:
21
22                   Before   /   After
23 Fast station 1:    19.17   /   25.09 Mbps
24 Fast station 2:    19.83   /   25.21 Mbps
25 Slow station:       2.58   /    1.77 Mbps
26 Total:             41.58   /   52.07 Mbps
27
28 The benefit of airtime fairness goes up the more stations are present.
29 In a 30-station test with one station artificially limited to 1 Mbps,
30 we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
31
32 Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
33 Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
34 ---
35
36 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
37 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
38 @@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *
39  #define ATH_TXFIFO_DEPTH           8
40  #define ATH_TX_ERROR               0x01
41  
42 +#define ATH_AIRTIME_QUANTUM        300 /* usec */
43 +
44  /* Stop tx traffic 1ms before the GO goes away */
45  #define ATH_P2P_PS_STOP_TIME       1000
46  
47 @@ -247,6 +249,9 @@ struct ath_atx_tid {
48         bool has_queued;
49  };
50  
51 +void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
52 +void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
53 +
54  struct ath_node {
55         struct ath_softc *sc;
56         struct ieee80211_sta *sta; /* station struct we're part of */
57 @@ -258,9 +263,12 @@ struct ath_node {
58  
59         bool sleeping;
60         bool no_ps_filter;
61 +       s64 airtime_deficit[IEEE80211_NUM_ACS];
62 +       u32 airtime_rx_start;
63  
64  #ifdef CPTCFG_ATH9K_STATION_STATISTICS
65         struct ath_rx_rate_stats rx_rate_stats;
66 +       struct ath_airtime_stats airtime_stats;
67  #endif
68         u8 key_idx[4];
69  
70 @@ -317,10 +325,16 @@ struct ath_rx {
71  /* Channel Context */
72  /*******************/
73  
74 +struct ath_acq {
75 +       struct list_head acq_new;
76 +       struct list_head acq_old;
77 +       spinlock_t lock;
78 +};
79 +
80  struct ath_chanctx {
81         struct cfg80211_chan_def chandef;
82         struct list_head vifs;
83 -       struct list_head acq[IEEE80211_NUM_ACS];
84 +       struct ath_acq acq[IEEE80211_NUM_ACS];
85         int hw_queue_base;
86  
87         /* do not dereference, use for comparison only */
88 @@ -575,6 +589,8 @@ void ath_txq_schedule_all(struct ath_sof
89  int ath_tx_init(struct ath_softc *sc, int nbufs);
90  int ath_txq_update(struct ath_softc *sc, int qnum,
91                    struct ath9k_tx_queue_info *q);
92 +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
93 +                    int width, int half_gi, bool shortPreamble);
94  void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
95  void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
96  int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
97 @@ -963,6 +979,11 @@ void ath_ant_comb_scan(struct ath_softc
98  
99  #define ATH9K_NUM_CHANCTX  2 /* supports 2 operating channels */
100  
101 +#define AIRTIME_USE_TX         BIT(0)
102 +#define AIRTIME_USE_RX         BIT(1)
103 +#define AIRTIME_USE_NEW_QUEUES BIT(2)
104 +#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
105 +
106  struct ath_softc {
107         struct ieee80211_hw *hw;
108         struct device *dev;
109 @@ -1005,6 +1026,8 @@ struct ath_softc {
110         short nbcnvifs;
111         unsigned long ps_usecount;
112  
113 +       u16 airtime_flags; /* AIRTIME_* */
114 +
115         struct ath_rx rx;
116         struct ath_tx tx;
117         struct ath_beacon beacon;
118 --- a/drivers/net/wireless/ath/ath9k/channel.c
119 +++ b/drivers/net/wireless/ath/ath9k/channel.c
120 @@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *
121                 INIT_LIST_HEAD(&ctx->vifs);
122                 ctx->txpower = ATH_TXPOWER_MAX;
123                 ctx->flush_timeout = HZ / 5; /* 200ms */
124 -               for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
125 -                       INIT_LIST_HEAD(&ctx->acq[j]);
126 +               for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
127 +                       INIT_LIST_HEAD(&ctx->acq[j].acq_new);
128 +                       INIT_LIST_HEAD(&ctx->acq[j].acq_old);
129 +                       spin_lock_init(&ctx->acq[j].lock);
130 +               }
131         }
132  }
133  
134 @@ -1345,8 +1348,11 @@ void ath9k_offchannel_init(struct ath_so
135         ctx->txpower = ATH_TXPOWER_MAX;
136         cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
137  
138 -       for (i = 0; i < ARRAY_SIZE(ctx->acq); i++)
139 -               INIT_LIST_HEAD(&ctx->acq[i]);
140 +       for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
141 +               INIT_LIST_HEAD(&ctx->acq[i].acq_new);
142 +               INIT_LIST_HEAD(&ctx->acq[i].acq_old);
143 +               spin_lock_init(&ctx->acq[i].lock);
144 +       }
145  
146         sc->offchannel.chan.offchannel = true;
147  }
148 --- a/drivers/net/wireless/ath/ath9k/debug.c
149 +++ b/drivers/net/wireless/ath/ath9k/debug.c
150 @@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah)
151         debugfs_create_file("tpc", S_IRUSR | S_IWUSR,
152                             sc->debug.debugfs_phy, sc, &fops_tpc);
153  
154 +       debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR,
155 +                          sc->debug.debugfs_phy, &sc->airtime_flags);
156 +
157         return 0;
158  }
159 --- a/drivers/net/wireless/ath/ath9k/debug.h
160 +++ b/drivers/net/wireless/ath/ath9k/debug.h
161 @@ -221,6 +221,11 @@ struct ath_rx_rate_stats {
162         } cck_stats[4];
163  };
164  
165 +struct ath_airtime_stats {
166 +       u32 rx_airtime;
167 +       u32 tx_airtime;
168 +};
169 +
170  #define ANT_MAIN 0
171  #define ANT_ALT  1
172  
173 @@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc
174  void ath_debug_rate_stats(struct ath_softc *sc,
175                           struct ath_rx_status *rs,
176                           struct sk_buff *skb);
177 +void ath_debug_airtime(struct ath_softc *sc,
178 +                      struct ath_node *an,
179 +                      u32 rx, u32 tx);
180  #else
181  static inline void ath_debug_rate_stats(struct ath_softc *sc,
182                                         struct ath_rx_status *rs,
183                                         struct sk_buff *skb)
184  {
185  }
186 +static inline void ath_debug_airtime(struct ath_softc *sc,
187 +                             struct ath_node *an,
188 +                             u32 rx, u32 tx)
189 +{
190 +}
191  #endif /* CPTCFG_ATH9K_STATION_STATISTICS */
192  
193  #endif /* DEBUG_H */
194 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c
195 +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
196 @@ -242,6 +242,59 @@ static const struct file_operations fops
197         .llseek = default_llseek,
198  };
199  
200 +void ath_debug_airtime(struct ath_softc *sc,
201 +               struct ath_node *an,
202 +               u32 rx,
203 +               u32 tx)
204 +{
205 +       struct ath_airtime_stats *astats = &an->airtime_stats;
206 +
207 +       astats->rx_airtime += rx;
208 +       astats->tx_airtime += tx;
209 +}
210 +
211 +static ssize_t read_airtime(struct file *file, char __user *user_buf,
212 +                       size_t count, loff_t *ppos)
213 +{
214 +       struct ath_node *an = file->private_data;
215 +       struct ath_airtime_stats *astats;
216 +       static const char *qname[4] = {
217 +               "VO", "VI", "BE", "BK"
218 +       };
219 +       u32 len = 0, size = 256;
220 +       char *buf;
221 +       size_t retval;
222 +       int i;
223 +
224 +       buf = kzalloc(size, GFP_KERNEL);
225 +       if (buf == NULL)
226 +               return -ENOMEM;
227 +
228 +       astats = &an->airtime_stats;
229 +
230 +       len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
231 +       len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
232 +       len += scnprintf(buf + len, size - len, "Deficit: ");
233 +       for (i = 0; i < 4; i++)
234 +               len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
235 +       if (len < size)
236 +               buf[len++] = '\n';
237 +
238 +       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
239 +       kfree(buf);
240 +
241 +       return retval;
242 +}
243 +
244 +
245 +static const struct file_operations fops_airtime = {
246 +       .read = read_airtime,
247 +       .open = simple_open,
248 +       .owner = THIS_MODULE,
249 +       .llseek = default_llseek,
250 +};
251 +
252 +
253  void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
254                            struct ieee80211_vif *vif,
255                            struct ieee80211_sta *sta,
256 @@ -251,4 +304,5 @@ void ath9k_sta_add_debugfs(struct ieee80
257  
258         debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr);
259         debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
260 +       debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime);
261  }
262 --- a/drivers/net/wireless/ath/ath9k/init.c
263 +++ b/drivers/net/wireless/ath/ath9k/init.c
264 @@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, s
265  
266         /* Will be cleared in ath9k_start() */
267         set_bit(ATH_OP_INVALID, &common->op_flags);
268 +       sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
269 +                            AIRTIME_USE_NEW_QUEUES);
270  
271         sc->sc_ah = ah;
272         sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
273 --- a/drivers/net/wireless/ath/ath9k/main.c
274 +++ b/drivers/net/wireless/ath/ath9k/main.c
275 @@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(str
276                 goto out;
277  
278         if (txq->mac80211_qnum >= 0) {
279 -               struct list_head *list;
280 +               struct ath_acq *acq;
281  
282 -               list = &sc->cur_chan->acq[txq->mac80211_qnum];
283 -               if (!list_empty(list))
284 +               acq = &sc->cur_chan->acq[txq->mac80211_qnum];
285 +               if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old))
286                         pending = true;
287         }
288  out:
289 --- a/drivers/net/wireless/ath/ath9k/recv.c
290 +++ b/drivers/net/wireless/ath/ath9k/recv.c
291 @@ -991,6 +991,70 @@ static void ath9k_apply_ampdu_details(st
292         }
293  }
294  
295 +static void ath_rx_count_airtime(struct ath_softc *sc,
296 +                                struct ath_rx_status *rs,
297 +                                struct sk_buff *skb)
298 +{
299 +       struct ath_node *an;
300 +       struct ath_acq *acq;
301 +       struct ath_vif *avp;
302 +       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
303 +       struct ath_hw *ah = sc->sc_ah;
304 +       struct ath_common *common = ath9k_hw_common(ah);
305 +       struct ieee80211_sta *sta;
306 +       struct ieee80211_rx_status *rxs;
307 +       const struct ieee80211_rate *rate;
308 +       bool is_sgi, is_40, is_sp;
309 +       int phy;
310 +       u16 len = rs->rs_datalen;
311 +       u32 airtime = 0;
312 +       u8 tidno, acno;
313 +
314 +       if (!ieee80211_is_data(hdr->frame_control))
315 +               return;
316 +
317 +       rcu_read_lock();
318 +
319 +       sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
320 +       if (!sta)
321 +               goto exit;
322 +       an = (struct ath_node *) sta->drv_priv;
323 +       avp = (struct ath_vif *) an->vif->drv_priv;
324 +       tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
325 +       acno = TID_TO_WME_AC(tidno);
326 +       acq = &avp->chanctx->acq[acno];
327 +
328 +       rxs = IEEE80211_SKB_RXCB(skb);
329 +
330 +       is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI);
331 +       is_40 = !!(rxs->flag & RX_FLAG_40MHZ);
332 +       is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE);
333 +
334 +       if (!!(rxs->flag & RX_FLAG_HT)) {
335 +               /* MCS rates */
336 +
337 +               airtime += ath_pkt_duration(sc, rxs->rate_idx, len,
338 +                                       is_40, is_sgi, is_sp);
339 +       } else {
340 +
341 +               phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM;
342 +               rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx];
343 +               airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100,
344 +                                               len, rxs->rate_idx, is_sp);
345 +       }
346 +
347 +       if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
348 +               spin_lock_bh(&acq->lock);
349 +               an->airtime_deficit[acno] -= airtime;
350 +               if (an->airtime_deficit[acno] <= 0)
351 +                       __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
352 +               spin_unlock_bh(&acq->lock);
353 +       }
354 +       ath_debug_airtime(sc, an, airtime, 0);
355 +exit:
356 +       rcu_read_unlock();
357 +}
358 +
359  int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
360  {
361         struct ath_rxbuf *bf;
362 @@ -1137,6 +1201,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
363                 ath9k_antenna_check(sc, &rs);
364                 ath9k_apply_ampdu_details(sc, &rs, rxs);
365                 ath_debug_rate_stats(sc, &rs, skb);
366 +               ath_rx_count_airtime(sc, &rs, skb);
367  
368                 hdr = (struct ieee80211_hdr *)skb->data;
369                 if (ieee80211_is_ack(hdr->frame_control))
370 --- a/drivers/net/wireless/ath/ath9k/xmit.c
371 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
372 @@ -125,21 +125,44 @@ void ath_txq_unlock_complete(struct ath_
373                 ath_tx_status(hw, skb);
374  }
375  
376 -static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
377 -                            struct ath_atx_tid *tid)
378 +void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
379  {
380 -       struct list_head *list;
381         struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
382         struct ath_chanctx *ctx = avp->chanctx;
383 +       struct ath_acq *acq;
384 +       struct list_head *tid_list;
385 +       u8 acno = TID_TO_WME_AC(tid->tidno);
386  
387 -       if (!ctx)
388 +       if (!ctx || !list_empty(&tid->list))
389                 return;
390  
391 -       list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
392 -       if (list_empty(&tid->list))
393 -               list_add_tail(&tid->list, list);
394 +
395 +       acq = &ctx->acq[acno];
396 +       if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) &&
397 +           tid->an->airtime_deficit[acno] > 0)
398 +               tid_list = &acq->acq_new;
399 +       else
400 +               tid_list = &acq->acq_old;
401 +
402 +       list_add_tail(&tid->list, tid_list);
403  }
404  
405 +void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
406 +{
407 +       struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
408 +       struct ath_chanctx *ctx = avp->chanctx;
409 +       struct ath_acq *acq;
410 +
411 +       if (!ctx || !list_empty(&tid->list))
412 +               return;
413 +
414 +       acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
415 +       spin_lock_bh(&acq->lock);
416 +       __ath_tx_queue_tid(sc, tid);
417 +       spin_unlock_bh(&acq->lock);
418 +}
419 +
420 +
421  void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
422  {
423         struct ath_softc *sc = hw->priv;
424 @@ -154,7 +177,7 @@ void ath9k_wake_tx_queue(struct ieee8021
425         ath_txq_lock(sc, txq);
426  
427         tid->has_queued = true;
428 -       ath_tx_queue_tid(sc, txq, tid);
429 +       ath_tx_queue_tid(sc, tid);
430         ath_txq_schedule(sc, txq);
431  
432         ath_txq_unlock(sc, txq);
433 @@ -684,7 +707,7 @@ static void ath_tx_complete_aggr(struct
434  
435                 skb_queue_splice_tail(&bf_pending, &tid->retry_q);
436                 if (!an->sleeping) {
437 -                       ath_tx_queue_tid(sc, txq, tid);
438 +                       ath_tx_queue_tid(sc, tid);
439  
440                         if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
441                                 tid->clear_ps_filter = true;
442 @@ -712,6 +735,53 @@ static bool bf_is_ampdu_not_probing(stru
443      return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
444  }
445  
446 +static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq,
447 +                                struct ath_buf *bf, struct ath_tx_status *ts)
448 +{
449 +       struct ath_node *an;
450 +       struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum];
451 +       struct sk_buff *skb;
452 +       struct ieee80211_hdr *hdr;
453 +       struct ieee80211_hw *hw = sc->hw;
454 +       struct ieee80211_tx_rate rates[4];
455 +       struct ieee80211_sta *sta;
456 +       int i;
457 +       u32 airtime = 0;
458 +
459 +       skb = bf->bf_mpdu;
460 +       if(!skb)
461 +               return;
462 +
463 +       hdr = (struct ieee80211_hdr *)skb->data;
464 +       memcpy(rates, bf->rates, sizeof(rates));
465 +
466 +       rcu_read_lock();
467 +
468 +       sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
469 +       if(!sta)
470 +               goto exit;
471 +
472 +
473 +       an = (struct ath_node *) sta->drv_priv;
474 +
475 +       airtime += ts->duration * (ts->ts_longretry + 1);
476 +
477 +       for(i=0; i < ts->ts_rateindex; i++)
478 +               airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count;
479 +
480 +       if (!!(sc->airtime_flags & AIRTIME_USE_TX)) {
481 +               spin_lock_bh(&acq->lock);
482 +               an->airtime_deficit[txq->mac80211_qnum] -= airtime;
483 +               if (an->airtime_deficit[txq->mac80211_qnum] <= 0)
484 +                       __ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb));
485 +               spin_unlock_bh(&acq->lock);
486 +       }
487 +       ath_debug_airtime(sc, an, 0, airtime);
488 +
489 +exit:
490 +       rcu_read_unlock();
491 +}
492 +
493  static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
494                                   struct ath_tx_status *ts, struct ath_buf *bf,
495                                   struct list_head *bf_head)
496 @@ -733,6 +803,7 @@ static void ath_tx_process_buffer(struct
497  
498         ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
499                                              ts->ts_rateindex);
500 +       ath_tx_count_airtime(sc, txq, bf, ts);
501  
502         hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
503         sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
504 @@ -1094,8 +1165,8 @@ finish:
505   * width  - 0 for 20 MHz, 1 for 40 MHz
506   * half_gi - to use 4us v/s 3.6 us for symbol time
507   */
508 -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
509 -                           int width, int half_gi, bool shortPreamble)
510 +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
511 +                    int width, int half_gi, bool shortPreamble)
512  {
513         u32 nbits, nsymbits, duration, nsymbols;
514         int streams;
515 @@ -1493,7 +1564,7 @@ ath_tx_form_burst(struct ath_softc *sc,
516  }
517  
518  static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
519 -                             struct ath_atx_tid *tid, bool *stop)
520 +                             struct ath_atx_tid *tid)
521  {
522         struct ath_buf *bf;
523         struct ieee80211_tx_info *tx_info;
524 @@ -1515,7 +1586,6 @@ static bool ath_tx_sched_aggr(struct ath
525         if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
526             (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
527                 __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
528 -               *stop = true;
529                 return false;
530         }
531  
532 @@ -1639,7 +1709,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
533                 ath_txq_lock(sc, txq);
534                 tid->clear_ps_filter = true;
535                 if (ath_tid_has_buffered(tid)) {
536 -                       ath_tx_queue_tid(sc, txq, tid);
537 +                       ath_tx_queue_tid(sc, tid);
538                         ath_txq_schedule(sc, txq);
539                 }
540                 ath_txq_unlock_complete(sc, txq);
541 @@ -1956,9 +2026,10 @@ void ath_tx_cleanupq(struct ath_softc *s
542  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
543  {
544         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
545 -       struct ath_atx_tid *tid, *last_tid;
546 +       struct ath_atx_tid *tid;
547         struct list_head *tid_list;
548 -       bool sent = false;
549 +       struct ath_acq *acq;
550 +       bool active = AIRTIME_ACTIVE(sc->airtime_flags);
551  
552         if (txq->mac80211_qnum < 0)
553                 return;
554 @@ -1967,48 +2038,55 @@ void ath_txq_schedule(struct ath_softc *
555                 return;
556  
557         spin_lock_bh(&sc->chan_lock);
558 -       tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
559 -
560 -       if (list_empty(tid_list)) {
561 -               spin_unlock_bh(&sc->chan_lock);
562 -               return;
563 -       }
564 -
565         rcu_read_lock();
566 +       acq = &sc->cur_chan->acq[txq->mac80211_qnum];
567  
568 -       last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
569 -       while (!list_empty(tid_list)) {
570 -               bool stop = false;
571 -
572 -               if (sc->cur_chan->stopped)
573 -                       break;
574 -
575 -               tid = list_first_entry(tid_list, struct ath_atx_tid, list);
576 -               list_del_init(&tid->list);
577 +       if (sc->cur_chan->stopped)
578 +               goto out;
579  
580 -               if (ath_tx_sched_aggr(sc, txq, tid, &stop))
581 -                       sent = true;
582 +begin:
583 +       tid_list = &acq->acq_new;
584 +       if (list_empty(tid_list)) {
585 +               tid_list = &acq->acq_old;
586 +               if (list_empty(tid_list))
587 +                       goto out;
588 +       }
589 +       tid = list_first_entry(tid_list, struct ath_atx_tid, list);
590  
591 -               /*
592 -                * add tid to round-robin queue if more frames
593 -                * are pending for the tid
594 -                */
595 -               if (ath_tid_has_buffered(tid))
596 -                       ath_tx_queue_tid(sc, txq, tid);
597 +       if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
598 +               spin_lock_bh(&acq->lock);
599 +               tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM;
600 +               list_move_tail(&tid->list, &acq->acq_old);
601 +               spin_unlock_bh(&acq->lock);
602 +               goto begin;
603 +       }
604  
605 -               if (stop)
606 -                       break;
607 +       if (!ath_tid_has_buffered(tid)) {
608 +               spin_lock_bh(&acq->lock);
609 +               if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old))
610 +                       list_move_tail(&tid->list, &acq->acq_old);
611 +               else {
612 +                       list_del_init(&tid->list);
613 +               }
614 +               spin_unlock_bh(&acq->lock);
615 +               goto begin;
616 +       }
617  
618 -               if (tid == last_tid) {
619 -                       if (!sent)
620 -                               break;
621  
622 -                       sent = false;
623 -                       last_tid = list_entry(tid_list->prev,
624 -                                             struct ath_atx_tid, list);
625 +       /*
626 +        * If we succeed in scheduling something, immediately restart to make
627 +        * sure we keep the HW busy.
628 +        */
629 +       if(ath_tx_sched_aggr(sc, txq, tid)) {
630 +               if (!active) {
631 +                       spin_lock_bh(&acq->lock);
632 +                       list_move_tail(&tid->list, &acq->acq_old);
633 +                       spin_unlock_bh(&acq->lock);
634                 }
635 +               goto begin;
636         }
637  
638 +out:
639         rcu_read_unlock();
640         spin_unlock_bh(&sc->chan_lock);
641  }
642 @@ -2862,6 +2940,9 @@ void ath_tx_node_init(struct ath_softc *
643         struct ath_atx_tid *tid;
644         int tidno, acno;
645  
646 +       for (acno = 0; acno < IEEE80211_NUM_ACS; acno++)
647 +               an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM;
648 +
649         for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
650                 tid = ath_node_to_tid(an, tidno);
651                 tid->an        = an;