On 2018-11-14 18:40, Toke Høiland-Jørgensen wrote: >> This part doesn't really make much sense to me, but maybe I'm >> misunderstanding how the code works. >> Let's assume we have a driver like ath9k or mt76, which tries to keep a >> number of aggregates in the hardware queue, and the hardware queue is >> currently empty. >> If the current txq entry is kept at the head of the schedule list, >> wouldn't the code just pull from that one over and over again, until >> enough packets are transmitted by the hardware and their tx status >> processed? >> It seems to me that while fairness is still preserved in the long run, >> this could lead to rather bursty scheduling, which may not be >> particularly latency friendly. > > Yes, it'll be a bit more bursty when the hardware queue is completely > empty. However, when a TX completion comes back, that will adjust the > deficit of that sta and cause it to be rotated on the next dequeue. This > obviously relies on the fact that the lower-level hardware queue is > sufficiently shallow to not add a lot of latency. But we want that to be > the case anyway. In practice, it works quite well for ath9k, but not so > well for ath10k because it has a large buffer in firmware. > > If we requeue the TXQ at the end of the list, a station that is taking > up too much airtime will fail to be throttled properly, so the > queue-at-head is kinda needed to ensure fairness... Thanks for the explanation, that makes sense to me. I have an idea on how to mitigate the burstiness within the driver. I'll write it down in pseudocode, please let me know if you think that'll work. do { struct ieee80211_txq *pending_txq[4]; int n_pending_txq = 0; int i; if (hwq->pending < 4) break; nframes = 0; ieee80211_txq_schedule_start(hw, ac) do { bool requeue = false; struct ieee80211_txq *txq; txq = ieee80211_next_txq(hw, ac); if (!txq) break; nframes += schedule_txq(txq, &requeue); if (requeue) pending_txq[n_pending_txq++] = txq; } while (n_pending_txq < ARRAY_SIZE(pending_txq)); for (i = n_pending_txq; i > 0; i--) ieee80211_return_txq(hw, pending_txq[i - 1]); ieee80211_txq_schedule_end(hw, ac) } while (nframes); - Felix