From: Julius Bairaktaris <julius@bairaktaris.de>
To: johannes@sipsolutions.net
Cc: toke@toke.dk, jjohnson@kernel.org, ath11k@lists.infradead.org,
linux-wireless@vger.kernel.org
Subject: [PATCH v2 1/2] wifi: mac80211: scale the airtime queue limit by the station's weight
Date: Tue, 8 Sep 2026 15:53:14 +0200 [thread overview]
Message-ID: <20260908135315.754126-1-julius@bairaktaris.de> (raw)
A driver that hands every frame it dequeues to the hardware at once
holds nothing back but the airtime queue limit, so every station keeps
its full limit in flight and the hardware picks the next transmitter
among them. The order in which ieee80211_next_txq() serves the queues
never reaches the air, and the airtime weight has no effect on the
airtime a station gets. ath11k is such a driver.
Add IEEE80211_HW_TX_NO_PUSHBACK for a driver to say so, and scale the
per-station limits by the weight when it is set. A station with twice
the default weight may keep twice the limit in flight. The scaled value
is capped at aql_threshold and never drops below the configured limit.
A driver without the flag is not affected.
Measured on an IPQ8074 AP with ath11k, a 2x2 HE160 and a 1x1 VHT80
client both saturated downstream, BE aql_txq_limit 500/1000 us, 15 s
runs, three per setting. Share of the tx airtime taken by the HE160
client in per cent, at weights 256:256, 1024:256 and 256:1024:
without the flag 55.2, 54.1, 52.8 55.9, 51.9, 59.8 54.8, 56.3, 59.2
with the flag 57.8, 57.5, 55.1 73.8, 76.7, 74.4 22.6, 22.7, 22.4
Mid-run the favoured client holds 1.2 to 3.2 ms in flight and the
other stays at the configured 1 ms.
Ping from the AP to the HE160 client under the same load is 4.8 to
7.4 ms mean at equal weights and 18.1 to 25.1 ms at 1024:256, where it
is the favoured client: the deeper queue costs it that latency.
The scaled limit takes effect only where the configured one binds. At
the default 5000/12000 us both clients hold several milliseconds in
flight, neither queue runs empty between transmissions, and the weight
does not move the split.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
---
v2:
- gate on a new hw flag, IEEE80211_HW_TX_NO_PUSHBACK, so a driver that
pulls when the hardware has room is not affected. The flag is set by
the driver rather than derived from the use of
ieee80211_handle_wake_tx_queue(): a driver with its own callback can
push everything it dequeues just the same, and ath11k does once it
schedules its TXQs itself
- add the ath11k patch that sets the flag as 2/2
- rewrite the message
- v1: https://lore.kernel.org/linux-wireless/20260824142435.1757391-1-julius@bairaktaris.de/
Measured with the ath11k series "wifi: ath11k: airtime queue limits,
fairness and a driver TXQ scheduler" v4 applied, which advertises AQL
and airtime fairness on ath11k, and with "wifi: mac80211: keep the TXQ
scheduling round number across a closed round" applied.
include/net/mac80211.h | 7 +++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/tx.c | 21 +++++++++++++++++++--
3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7bb4618065b6..80381c7abd84 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3086,6 +3086,12 @@ struct ieee80211_txq {
* @IEEE80211_HW_SUPPORTS_NDP_BLOCKACK: HW can transmit/receive S1G NDP
* BlockAck frames.
*
+ * @IEEE80211_HW_TX_NO_PUSHBACK: The driver hands every frame it dequeues
+ * to the hardware at once, and the hardware picks the station it serves
+ * next, so the order in which mac80211 schedules the queues does not
+ * reach the air. mac80211 then applies the airtime weight to the
+ * airtime queue limit instead.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -3147,6 +3153,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_HANDLES_QUIET_CSA,
IEEE80211_HW_STRICT,
IEEE80211_HW_SUPPORTS_NDP_BLOCKACK,
+ IEEE80211_HW_TX_NO_PUSHBACK,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 8946b027782c..ddbfa991ec74 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -462,6 +462,7 @@ static const char *hw_flag_names[] = {
FLAG(HANDLES_QUIET_CSA),
FLAG(STRICT),
FLAG(SUPPORTS_NDP_BLOCKACK),
+ FLAG(TX_NO_PUSHBACK),
#undef FLAG
};
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c33092960df2..c94efff48d74 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4217,6 +4217,21 @@ EXPORT_SYMBOL(__ieee80211_schedule_txq);
DEFINE_STATIC_KEY_FALSE(aql_disable);
+static u32 ieee80211_aql_sta_limit(struct ieee80211_local *local,
+ struct sta_info *sta, u32 limit)
+{
+ u32 scaled;
+
+ if (!ieee80211_hw_check(&local->hw, TX_NO_PUSHBACK) ||
+ 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)
{
@@ -4238,13 +4253,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
next reply other threads:[~2026-09-08 13:53 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 13:53 Julius Bairaktaris [this message]
2026-09-08 13:53 ` [PATCH v2 2/2] wifi: ath11k: declare that tx has no pushback Julius Bairaktaris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260908135315.754126-1-julius@bairaktaris.de \
--to=julius@bairaktaris.de \
--cc=ath11k@lists.infradead.org \
--cc=jjohnson@kernel.org \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=toke@toke.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox