* [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
@ 2026-08-24 14:24 Julius Bairaktaris
2026-09-04 9:21 ` Johannes Berg
0 siblings, 1 reply; 9+ messages in thread
From: Julius Bairaktaris @ 2026-08-24 14:24 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, toke
The airtime queue limit is the same for every station, so on a driver
that pushes a whole scheduling selection into the hardware, every station
is allowed the same airtime in flight and the deficit round robin can
only decide the order in which they reach that ceiling, not how much of
the medium each one gets. Setting NL80211_ATTR_AIRTIME_WEIGHT then has
no effect on the airtime a station receives.
Measured on an IPQ8074 access point with two stations on one radio, a 1x1
VHT80 client and a 2x2 HE160 client, both saturated from the access point
at once, BE aql_txq_limit at 500/1000 us, three interleaved runs per
weight with the association verified unchanged across every run. Without
this change the slow station takes 44.4, 43.9 and 44.0 per cent of the
medium at equal weights, 44.0, 43.5 and 44.4 at 1024:256, and 43.1, 43.4
and 42.8 at 256:1024. The weight moves the split by less than the spread
within one setting.
Scale the per-station limit by the station's weight. A station weighted
above the default is allowed proportionally more airtime in flight and
therefore takes proportionally more of the medium. A network that never
sets a weight is unaffected, since every station keeps the default.
The same pair then reads 42.1, 43.3 and 42.8 per cent at equal weights,
78.0, 78.9 and 77.2 at 1024:256, and 19.6, 18.3 and 20.0 at 256:1024: a
4:1 weight produces a 3.6:1 airtime ratio and 1:4 produces 4.2:1. It is
not free, and over the pair the aggregate is 557 Mbit/s at equal weights,
925 when the faster station is favoured and 337 when the slower one is.
The low limit is consulted without reference to the radio total, so the
scaled value is bounded by aql_threshold. Without that bound a weight of
65535 grants one station 1.3 seconds of standing airtime on the default
low limit, which no total accounts for. The bound reaches the high limit
as well, where it changes nothing: that check already requires the radio
total to sit below the same threshold.
The bound never reduces a limit below the value configured for it, so an
access point that raises aql_txq_limit above aql_threshold keeps what it
asked for at every weight, and scaling a weight up cannot scale a limit
down.
That bound is also the ceiling on what a weight can express. At the
default low limit of 5000 us it takes effect near a weight of 1229, so
ratios beyond roughly five to one do not resolve: a weight of 65535
against 256 asks for 256 to 1 and delivers 4.9 to 1.
This changes nothing where the limit does not bind. A station whose
pending airtime never approaches the limit is not held back by it at
either weight, mac80211 holds no backlog to arbitrate, and the share each
station gets is decided by the hardware's own scheduling.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
---
The measurements were taken on ath11k with the series "wifi: ath11k:
airtime queue limits, fairness and a driver TXQ scheduler", posted
separately to linux-wireless.
net/mac80211/tx.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3a1e2c9e1565..11350133d637 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4223,6 +4223,25 @@ EXPORT_SYMBOL(__ieee80211_schedule_txq);
DEFINE_STATIC_KEY_FALSE(aql_disable);
+/* The airtime a station may keep in flight scales with its weight. The low
+ * limit is consulted unconditionally, so the scaled value is bounded by the
+ * radio-wide threshold rather than by the weight alone, and never below the
+ * limit that was configured.
+ */
+static u32 ieee80211_aql_sta_limit(struct ieee80211_local *local,
+ struct sta_info *sta, u32 limit)
+{
+ u32 scaled;
+
+ if (sta->airtime_weight == IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+ return limit;
+
+ scaled = mult_frac(limit, sta->airtime_weight,
+ IEEE80211_DEFAULT_AIRTIME_WEIGHT);
+
+ return min(scaled, max(limit, local->aql_threshold));
+}
+
bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
@@ -4244,13 +4263,15 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
sta = container_of(txq->sta, struct sta_info, sta);
if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
- sta->airtime[txq->ac].aql_limit_low)
+ ieee80211_aql_sta_limit(local, sta,
+ sta->airtime[txq->ac].aql_limit_low))
return true;
if (atomic_read(&local->aql_total_pending_airtime) <
local->aql_threshold &&
atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
- sta->airtime[txq->ac].aql_limit_high)
+ ieee80211_aql_sta_limit(local, sta,
+ sta->airtime[txq->ac].aql_limit_high))
return true;
return false;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-08-24 14:24 [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight Julius Bairaktaris
@ 2026-09-04 9:21 ` Johannes Berg
2026-09-04 9:46 ` Julius Bairaktaris
0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2026-09-04 9:21 UTC (permalink / raw)
To: Julius Bairaktaris; +Cc: linux-wireless, toke
On Mon, 2026-08-24 at 16:24 +0200, Julius Bairaktaris wrote:
> The airtime queue limit is the same for every station, so on a driver
> that pushes a whole scheduling selection into the hardware, every station
> is allowed the same airtime in flight and the deficit round robin can
> only decide the order in which they reach that ceiling, not how much of
> the medium each one gets. Setting NL80211_ATTR_AIRTIME_WEIGHT then has
> no effect on the airtime a station receives.
>
> Measured on an IPQ8074 access point with two stations on one radio, a 1x1
> VHT80 client and a 2x2 HE160 client, both saturated from the access point
> at once, BE aql_txq_limit at 500/1000 us, three interleaved runs per
> weight with the association verified unchanged across every run. Without
> this change the slow station takes 44.4, 43.9 and 44.0 per cent of the
> medium at equal weights, 44.0, 43.5 and 44.4 at 1024:256, and 43.1, 43.4
> and 42.8 at 256:1024. The weight moves the split by less than the spread
> within one setting.
>
> Scale the per-station limit by the station's weight. A station weighted
> above the default is allowed proportionally more airtime in flight and
> therefore takes proportionally more of the medium. A network that never
> sets a weight is unaffected, since every station keeps the default.
>
> The same pair then reads 42.1, 43.3 and 42.8 per cent at equal weights,
> 78.0, 78.9 and 77.2 at 1024:256, and 19.6, 18.3 and 20.0 at 256:1024: a
> 4:1 weight produces a 3.6:1 airtime ratio and 1:4 produces 4.2:1. It is
> not free, and over the pair the aggregate is 557 Mbit/s at equal weights,
> 925 when the faster station is favoured and 337 when the slower one is.
>
> The low limit is consulted without reference to the radio total, so the
> scaled value is bounded by aql_threshold. Without that bound a weight of
> 65535 grants one station 1.3 seconds of standing airtime on the default
> low limit, which no total accounts for. The bound reaches the high limit
> as well, where it changes nothing: that check already requires the radio
> total to sit below the same threshold.
>
> The bound never reduces a limit below the value configured for it, so an
> access point that raises aql_txq_limit above aql_threshold keeps what it
> asked for at every weight, and scaling a weight up cannot scale a limit
> down.
>
> That bound is also the ceiling on what a weight can express. At the
> default low limit of 5000 us it takes effect near a weight of 1229, so
> ratios beyond roughly five to one do not resolve: a weight of 65535
> against 256 asks for 256 to 1 and delivers 4.9 to 1.
>
> This changes nothing where the limit does not bind. A station whose
> pending airtime never approaches the limit is not held back by it at
> either weight, mac80211 holds no backlog to arbitrate, and the share each
> station gets is decided by the hardware's own scheduling.
I can't really follow that. Do you understand the change?
> +/* The airtime a station may keep in flight scales with its weight. The low
> + * limit is consulted unconditionally, so the scaled value is bounded by the
> + * radio-wide threshold rather than by the weight alone, and never below the
> + * limit that was configured.
> + */
> +static u32 ieee80211_aql_sta_limit(struct ieee80211_local *local,
> + struct sta_info *sta, u32 limit)
> +{
> + u32 scaled;
> +
> + if (sta->airtime_weight == IEEE80211_DEFAULT_AIRTIME_WEIGHT)
> + return limit;
> +
> + scaled = mult_frac(limit, sta->airtime_weight,
airtime weight is already used to select when the queues are serviced,
so why should it be used for the queue depth?
johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 9:21 ` Johannes Berg
@ 2026-09-04 9:46 ` Julius Bairaktaris
2026-09-04 9:49 ` Johannes Berg
0 siblings, 1 reply; 9+ messages in thread
From: Julius Bairaktaris @ 2026-09-04 9:46 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, toke
Hi Johannes,
> airtime weight is already used to select when the queues are serviced,
> so why should it be used for the queue depth?
While I used AI to help me write the change, my understanding of it is
that on ath11k the order does not matter. mac80211 fills each station's
queue in the chip until the AQL limit is reached. This results in both
stations always having a full queue, leaving it to the chip to decide
which one to send next. I noticed this because in my tests changing
weights did nothing.
With the change, a station with a higher weight is allowed a deeper
queue in the chip. The chip then simply has more of that station to
send, and in my tests a 4:1 weight gave roughly a 4:1 airtime split.
I don't think this can be fixed in ath11k, since the chip never asks
mac80211 for a specific station and just sends what it is given. So
the only thing we can control is how much is handed over.
Julius
Am Fr., 4. Sept. 2026 um 09:21 Uhr schrieb Johannes Berg
<johannes@sipsolutions.net>:
>
> On Mon, 2026-08-24 at 16:24 +0200, Julius Bairaktaris wrote:
> > The airtime queue limit is the same for every station, so on a driver
> > that pushes a whole scheduling selection into the hardware, every station
> > is allowed the same airtime in flight and the deficit round robin can
> > only decide the order in which they reach that ceiling, not how much of
> > the medium each one gets. Setting NL80211_ATTR_AIRTIME_WEIGHT then has
> > no effect on the airtime a station receives.
> >
> > Measured on an IPQ8074 access point with two stations on one radio, a 1x1
> > VHT80 client and a 2x2 HE160 client, both saturated from the access point
> > at once, BE aql_txq_limit at 500/1000 us, three interleaved runs per
> > weight with the association verified unchanged across every run. Without
> > this change the slow station takes 44.4, 43.9 and 44.0 per cent of the
> > medium at equal weights, 44.0, 43.5 and 44.4 at 1024:256, and 43.1, 43.4
> > and 42.8 at 256:1024. The weight moves the split by less than the spread
> > within one setting.
> >
> > Scale the per-station limit by the station's weight. A station weighted
> > above the default is allowed proportionally more airtime in flight and
> > therefore takes proportionally more of the medium. A network that never
> > sets a weight is unaffected, since every station keeps the default.
> >
> > The same pair then reads 42.1, 43.3 and 42.8 per cent at equal weights,
> > 78.0, 78.9 and 77.2 at 1024:256, and 19.6, 18.3 and 20.0 at 256:1024: a
> > 4:1 weight produces a 3.6:1 airtime ratio and 1:4 produces 4.2:1. It is
> > not free, and over the pair the aggregate is 557 Mbit/s at equal weights,
> > 925 when the faster station is favoured and 337 when the slower one is.
> >
> > The low limit is consulted without reference to the radio total, so the
> > scaled value is bounded by aql_threshold. Without that bound a weight of
> > 65535 grants one station 1.3 seconds of standing airtime on the default
> > low limit, which no total accounts for. The bound reaches the high limit
> > as well, where it changes nothing: that check already requires the radio
> > total to sit below the same threshold.
> >
> > The bound never reduces a limit below the value configured for it, so an
> > access point that raises aql_txq_limit above aql_threshold keeps what it
> > asked for at every weight, and scaling a weight up cannot scale a limit
> > down.
> >
> > That bound is also the ceiling on what a weight can express. At the
> > default low limit of 5000 us it takes effect near a weight of 1229, so
> > ratios beyond roughly five to one do not resolve: a weight of 65535
> > against 256 asks for 256 to 1 and delivers 4.9 to 1.
> >
> > This changes nothing where the limit does not bind. A station whose
> > pending airtime never approaches the limit is not held back by it at
> > either weight, mac80211 holds no backlog to arbitrate, and the share each
> > station gets is decided by the hardware's own scheduling.
>
> I can't really follow that. Do you understand the change?
>
> > +/* The airtime a station may keep in flight scales with its weight. The low
> > + * limit is consulted unconditionally, so the scaled value is bounded by the
> > + * radio-wide threshold rather than by the weight alone, and never below the
> > + * limit that was configured.
> > + */
> > +static u32 ieee80211_aql_sta_limit(struct ieee80211_local *local,
> > + struct sta_info *sta, u32 limit)
> > +{
> > + u32 scaled;
> > +
> > + if (sta->airtime_weight == IEEE80211_DEFAULT_AIRTIME_WEIGHT)
> > + return limit;
> > +
> > + scaled = mult_frac(limit, sta->airtime_weight,
>
> airtime weight is already used to select when the queues are serviced,
> so why should it be used for the queue depth?
>
> johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 9:46 ` Julius Bairaktaris
@ 2026-09-04 9:49 ` Johannes Berg
2026-09-04 10:02 ` Julius Bairaktaris
0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2026-09-04 9:49 UTC (permalink / raw)
To: Julius Bairaktaris; +Cc: linux-wireless, toke
On Fri, 2026-09-04 at 09:46 +0000, Julius Bairaktaris wrote:
> Hi Johannes,
>
> > airtime weight is already used to select when the queues are serviced,
> > so why should it be used for the queue depth?
>
> While I used AI to help me write the change, my understanding of it is
> that on ath11k the order does not matter.
ath11k doesn't appear to use ieee80211_next_txq(), so it doesn't get
this and then AQL doesn't really work, I guess?
But for a driver that *does* use it, I believe this change is wrong.
johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 9:49 ` Johannes Berg
@ 2026-09-04 10:02 ` Julius Bairaktaris
2026-09-04 10:07 ` Johannes Berg
0 siblings, 1 reply; 9+ messages in thread
From: Julius Bairaktaris @ 2026-09-04 10:02 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, toke
> ath11k doesn't appear to use ieee80211_next_txq(), so it doesn't get
> this and then AQL doesn't really work, I guess?
ath11k is using the generic handler
drivers/net/wireless/ath/ath11k/mac.c:
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
which runs the ieee80211_next_txq() loop itself. What is missing is
the AQL feature bit and the airtime reporting, which my series on
ath-next adds. The numbers in this patch were taken with that series
applied, so AQL and the DRR were both active when the weight did
nothing.
> But for a driver that *does* use it, I believe this change is wrong.
I agree with that. It would have to be gated so that drivers like
ath9k don't get it.
There is also the possibility of dropping this change and letting
ath11k pass the weight to the firmware's own ATF, for which the WMI
commands are already in wmi.h but unused. I haven't tested this yet,
it's just a theory, but mac80211 would stay untouched. What do you
think?
Julius
Am Fr., 4. Sept. 2026 um 09:50 Uhr schrieb Johannes Berg
<johannes@sipsolutions.net>:
>
> On Fri, 2026-09-04 at 09:46 +0000, Julius Bairaktaris wrote:
> > Hi Johannes,
> >
> > > airtime weight is already used to select when the queues are serviced,
> > > so why should it be used for the queue depth?
> >
> > While I used AI to help me write the change, my understanding of it is
> > that on ath11k the order does not matter.
>
> ath11k doesn't appear to use ieee80211_next_txq(), so it doesn't get
> this and then AQL doesn't really work, I guess?
>
> But for a driver that *does* use it, I believe this change is wrong.
>
> johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 10:02 ` Julius Bairaktaris
@ 2026-09-04 10:07 ` Johannes Berg
2026-09-04 10:35 ` Julius Bairaktaris
0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2026-09-04 10:07 UTC (permalink / raw)
To: Julius Bairaktaris; +Cc: linux-wireless, toke
On Fri, 2026-09-04 at 10:02 +0000, Julius Bairaktaris wrote:
> > ath11k doesn't appear to use ieee80211_next_txq(), so it doesn't get
> > this and then AQL doesn't really work, I guess?
>
> ath11k is using the generic handler
>
> drivers/net/wireless/ath/ath11k/mac.c:
> .wake_tx_queue = ieee80211_handle_wake_tx_queue,
>
> which runs the ieee80211_next_txq() loop itself.
Oops, my bad.
> What is missing is
> the AQL feature bit and the airtime reporting, which my series on
> ath-next adds. The numbers in this patch were taken with that series
> applied, so AQL and the DRR were both active when the weight did
> nothing.
>
> > But for a driver that *does* use it, I believe this change is wrong.
>
> I agree with that. It would have to be gated so that drivers like
> ath9k don't get it.
Now I'm confused - I was thinking it'd be wrong _only_ for ath9k etc.,
but you just corrected me and said that ieee80211_next_txq() is called
anyway, so then wouldn't it also be wrong on ath11k? Or not wrong on
all?
> There is also the possibility of dropping this change and letting
> ath11k pass the weight to the firmware's own ATF, for which the WMI
> commands are already in wmi.h but unused. I haven't tested this yet,
> it's just a theory, but mac80211 would stay untouched. What do you
> think?
No idea, sorry.
johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 10:07 ` Johannes Berg
@ 2026-09-04 10:35 ` Julius Bairaktaris
2026-09-04 11:46 ` Toke Høiland-Jørgensen
0 siblings, 1 reply; 9+ messages in thread
From: Julius Bairaktaris @ 2026-09-04 10:35 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, toke
> Now I'm confused - I was thinking it'd be wrong _only_ for ath9k etc.,
> but you just corrected me and said that ieee80211_next_txq() is called
> anyway, so then wouldn't it also be wrong on ath11k? Or not wrong on
> all?
Both run the DRR:
ath11k drains the selected queue until AQL stops it
net/mac80211/util.c, wake_tx_push_queue():
while (1) {
skb = ieee80211_tx_dequeue(&local->hw, queue);
so every station has a full queue in the chip and the firmware picks
the next one. The DRR order doesn't get exposed to the fw.
ath9k hands over one aggregate per selection
drivers/net/wireless/ath/ath9k/xmit.c, ath_tx_sched_aggr():
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
return -EBUSY;
so there the DRR order is the air order and the weight already works.
mac80211 can't tell those two apart, the driver would have to say it.
Would a hw flag be ok?
Julius
Am Fr., 4. Sept. 2026 um 10:07 Uhr schrieb Johannes Berg
<johannes@sipsolutions.net>:
>
> On Fri, 2026-09-04 at 10:02 +0000, Julius Bairaktaris wrote:
> > > ath11k doesn't appear to use ieee80211_next_txq(), so it doesn't get
> > > this and then AQL doesn't really work, I guess?
> >
> > ath11k is using the generic handler
> >
> > drivers/net/wireless/ath/ath11k/mac.c:
> > .wake_tx_queue = ieee80211_handle_wake_tx_queue,
> >
> > which runs the ieee80211_next_txq() loop itself.
>
> Oops, my bad.
>
> > What is missing is
> > the AQL feature bit and the airtime reporting, which my series on
> > ath-next adds. The numbers in this patch were taken with that series
> > applied, so AQL and the DRR were both active when the weight did
> > nothing.
> >
> > > But for a driver that *does* use it, I believe this change is wrong.
> >
> > I agree with that. It would have to be gated so that drivers like
> > ath9k don't get it.
>
> Now I'm confused - I was thinking it'd be wrong _only_ for ath9k etc.,
> but you just corrected me and said that ieee80211_next_txq() is called
> anyway, so then wouldn't it also be wrong on ath11k? Or not wrong on
> all?
>
> > There is also the possibility of dropping this change and letting
> > ath11k pass the weight to the firmware's own ATF, for which the WMI
> > commands are already in wmi.h but unused. I haven't tested this yet,
> > it's just a theory, but mac80211 would stay untouched. What do you
> > think?
>
> No idea, sorry.
>
> johannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 10:35 ` Julius Bairaktaris
@ 2026-09-04 11:46 ` Toke Høiland-Jørgensen
2026-09-08 13:52 ` Julius Bairaktaris
0 siblings, 1 reply; 9+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-04 11:46 UTC (permalink / raw)
To: Julius Bairaktaris, Johannes Berg; +Cc: linux-wireless
Julius Bairaktaris <julius@bairaktaris.de> writes:
>> Now I'm confused - I was thinking it'd be wrong _only_ for ath9k etc.,
>> but you just corrected me and said that ieee80211_next_txq() is called
>> anyway, so then wouldn't it also be wrong on ath11k? Or not wrong on
>> all?
>
> Both run the DRR:
>
> ath11k drains the selected queue until AQL stops it
>
> net/mac80211/util.c, wake_tx_push_queue():
> while (1) {
> skb = ieee80211_tx_dequeue(&local->hw, queue);
>
> so every station has a full queue in the chip and the firmware picks
> the next one. The DRR order doesn't get exposed to the fw.
>
> ath9k hands over one aggregate per selection
>
> drivers/net/wireless/ath/ath9k/xmit.c, ath_tx_sched_aggr():
> if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
> return -EBUSY;
>
> so there the DRR order is the air order and the weight already works.
ath9k doesn't use AQL at all (as you say, it schedules transmissions
directly), so that's not really relevant to any discussion of AQL :)
So I think the reason the weight is not working is that there's no
pushback from the driver in the wake_tx_push_queue() callback. The DRR
mechanism for achieving fairness (or, in the case of weights,
unfairness) is basically:
1. Driver pushes data to the hardware until the hardware buffer fills up.
Crucially, the assumption here is that there's a single shared buffer
that we fill.
2. When some space in the hardware becomes available it pulls the next
data, and DRR can influence the order of packets going into the
(shared) hardware buffer, which is how it controls the division of
airtime between stations.
Crucially, between 1. and 2. (i.e., from the buffer fills up until
there's space again), the driver does not pull any packets from the TXQs
until there's space again. In ath10k (for example) this is achieved by
the ath10k_mac_tx_can_push() check in its wake_tx_queue function.
However, the mac80211 implementation of wake_tx_queue() just calls
drv_tx() without any pushback, so every time a packet arrives, the push
function will re-run, iterating through the available TXQs and pushing
data into the driver. Looking at the ath11k specifically, it seems
that the driver will just keep pushing data into the hardware, only
stopping when it runs out of TX descriptors across all TX rings. At
which point I guess packets will just start getting dropped in drv_tx()?
Which means that for ath11k, stations will pretty much always have their
full AQL limit worth of packets enqueued in the firmware. And changing
that limit to take into account the weights does not seem like a totally
insane way of influencing the relative weight between stations in the
absence of other knobs. The main drawback is that this means that
giving a station a higher share of the airtime also translates into
worse latency for that station (as it'll have more data queued outside
the influence of fq_codel). It's not quite clear to me whether the
increased access to the medium will offset this.
An alternative to this approach would be to impose the global limit from
the mac80211 side by refusing to dequeue any packets into the hardware
while local->aql_total_pending_airtime is above a certain level. In
theory, at least, that should achieve the same thing by letting DRR do
its thing.
-Toke
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight
2026-09-04 11:46 ` Toke Høiland-Jørgensen
@ 2026-09-08 13:52 ` Julius Bairaktaris
0 siblings, 0 replies; 9+ messages in thread
From: Julius Bairaktaris @ 2026-09-08 13:52 UTC (permalink / raw)
To: toke, johannes, linux-wireless
Hi Toke,
> So I think the reason the weight is not working is that there's no
> pushback from the driver in the wake_tx_push_queue() callback.
I agree with that. v2 gates the scaling on a hw flag the driver sets
when it has no pushback, so a driver that pulls when the hardware has
room is not touched.
> An alternative to this approach would be to impose the global limit from
> the mac80211 side by refusing to dequeue any packets into the hardware
> while local->aql_total_pending_airtime is above a certain level.
I tried that with the knobs that exist: BE aql_txq_limit 0/12000 and
aql_threshold 4000, so only the total decides who refills. Same two
stations, three runs per weight, share of the HE160 client:
256:256 40.4 40.2 41.1
1024:256 44.5 39.3 43.9
256:1024 37.6 35.7 36.6
The weight does not move it. My understanding is that the deficit is
topped up too often to be scarce:
net/mac80211/tx.c, ieee80211_next_txq():
if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) {
sta->airtime[txqi->txq.ac].deficit +=
sta->airtime_weight;
...
}
With my ath11k series a round runs for every frame from the stack and
for every completion batch, and every round adds the weight to each
station that is negative. A PPDU charges a few thousand us once, the
top-ups come tens of thousands of times a second, so a deficit is back
above zero long before the next completion frees room, and the first
queue in the list takes the room. This was measured with the series
applied, so the round frequency is mine, not upstream's. For the cap to
work the way you describe, the driver would also have to stop starting
rounds while the total is over it, like ath10k does. I haven't tried
that variant.
> The main drawback is that this means that giving a station a higher
> share of the airtime also translates into worse latency for that station
At 500/1000 I do see it now. Ping from the AP to the HE160 client under
load at 1024:256 reads 18.1, 25.1 and 19.0 ms mean with the scaling,
against 4.8, 7.4 and 6.9 at equal weights on the same image, and 4.7 to
34.2 without the scaling, three runs each. The favoured station holds
up to four times the limit in flight and its latency goes with it. The
v2 message says so. That ping goes through the client's own txq, behind
its queue in mac80211 and its limit in the hardware; a probe that enters
by another path lands in a TCL ring the download does not fill and stays
flat, which is what the ath11k cover reports.
v2 does that with IEEE80211_HW_TX_NO_PUSHBACK, set by the driver; if
there is a better way for the driver to say it I will change it.
Julius
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-08 13:53 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 14:24 [PATCH] wifi: mac80211: scale the airtime queue limit by the station's weight Julius Bairaktaris
2026-09-04 9:21 ` Johannes Berg
2026-09-04 9:46 ` Julius Bairaktaris
2026-09-04 9:49 ` Johannes Berg
2026-09-04 10:02 ` Julius Bairaktaris
2026-09-04 10:07 ` Johannes Berg
2026-09-04 10:35 ` Julius Bairaktaris
2026-09-04 11:46 ` Toke Høiland-Jørgensen
2026-09-08 13:52 ` Julius Bairaktaris
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox