From: Julius Bairaktaris <julius@bairaktaris.de>
To: jjohnson@kernel.org
Cc: linux-wireless@vger.kernel.org, ath11k@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: [PATCH ath-next v2 6/9] wifi: ath11k: run the TXQ scheduler on tx completion
Date: Mon, 24 Aug 2026 09:42:25 +0200 [thread overview]
Message-ID: <20260824074228.2114579-7-julius@bairaktaris.de> (raw)
In-Reply-To: <20260824074228.2114579-1-julius@bairaktaris.de>
A station whose airtime queue limit is reached stops being served by
ieee80211_tx_dequeue(), and the airtime it is waiting on is only
returned when the hardware completes the frames already charged to it.
ath11k starts a scheduling round from the wake_tx_queue callback and
nowhere else, so once the limit binds, the backlog moves again only when
the next frame arrives from the network stack. Under a saturated
download the arrivals keep the round running; a flow that has just
filled the intermediate queue, or one whose sender is waiting on the
acknowledgements behind that queue, stalls for as long as it takes the
next arrival to appear.
Start a round for every radio whose completions were reaped, at the
point where the airtime has been returned. The airtime queue limit then
bounds a queue that is refilled as it drains, rather than one that is
refilled when the network stack happens to push.
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
Assisted-by: Claude:claude-opus-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
---
drivers/net/wireless/ath/ath11k/dp_tx.c | 12 +++++++++++-
drivers/net/wireless/ath/ath11k/mac.c | 10 ++++++++++
drivers/net/wireless/ath/ath11k/mac.h | 1 +
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 52c4a9924a31..2270b2079297 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -694,9 +694,10 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
struct sk_buff *msdu;
struct hal_tx_status ts = {};
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
+ unsigned long push = 0;
u32 *desc;
u32 msdu_id;
- u8 mac_id;
+ u8 mac_id, i;
spin_lock_bh(&status_ring->lock);
@@ -756,12 +757,21 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
spin_unlock(&tx_ring->tx_idr_lock);
ar = ab->pdevs[mac_id].ar;
+ __set_bit(mac_id, &push);
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
ath11k_dp_tx_complete_msdu(ar, msdu, &ts);
}
+
+ /* A completion returns the airtime the frame was charged, which is
+ * what an airtime-limited station is waiting on. Nothing else starts a
+ * scheduling round once the arrivals that would have started one are
+ * queued behind that limit.
+ */
+ for_each_set_bit(i, &push, ab->num_radios)
+ ath11k_mac_tx_push_pending(ab->pdevs[i].ar);
}
int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index e5b2a5e56a28..996f421b6957 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6582,6 +6582,16 @@ static void ath11k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
ath11k_mac_schedule_txq(hw->priv, txq->ac);
}
+void ath11k_mac_tx_push_pending(struct ath11k *ar)
+{
+ u8 ac;
+
+ rcu_read_lock();
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ ath11k_mac_schedule_txq(ar, ac);
+ rcu_read_unlock();
+}
+
void ath11k_mac_drain_tx(struct ath11k *ar)
{
/* make sure rcu-protected mac80211 tx path itself is drained */
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 59f83c7175fd..4012155dddb6 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -161,6 +161,7 @@ struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id)
struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id);
void ath11k_mac_drain_tx(struct ath11k *ar);
+void ath11k_mac_tx_push_pending(struct ath11k *ar);
void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
--
2.53.0
next prev parent reply other threads:[~2026-08-24 7:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 7:42 [PATCH ath-next v2 0/9] wifi: ath11k: airtime queue limits, fairness and a driver TXQ scheduler Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 1/9] wifi: ath11k: free tx skbs through ieee80211_free_txskb() Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 2/9] wifi: ath11k: enable airtime queue limits Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 3/9] wifi: ath11k: report the pending tx MSDU count in soc_dp_stats Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 4/9] wifi: ath11k: report tx airtime and enable airtime fairness Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 5/9] wifi: ath11k: schedule TXQs from the driver Julius Bairaktaris
2026-08-24 7:42 ` Julius Bairaktaris [this message]
2026-08-24 7:42 ` [PATCH ath-next v2 7/9] wifi: ath11k: charge received airtime to the station deficit Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 8/9] wifi: ath11k: stop a scheduling round when the hardware refuses a frame Julius Bairaktaris
2026-08-24 7:42 ` [PATCH ath-next v2 9/9] wifi: ath11k: budget the tx completion handler 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=20260824074228.2114579-7-julius@bairaktaris.de \
--to=julius@bairaktaris.de \
--cc=ath11k@lists.infradead.org \
--cc=jjohnson@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
/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