[RFC PATCH] wifi: ath12k: service all RX rings in an interrupt group

John dencity7 at gmail.com
Mon Oct 5 17:48:43 PDT 2026


An RX interrupt group may select multiple receive rings. The Wi-Fi 7
handler currently services only the highest set bit, even when the NAPI
budget has room for work from another selected ring. Walk all selected
bits and retain the shared budget and existing early-exit behavior.

On a locally adapted GL-BE3600/QCN6432, group 5 selects bits 2 and 3. A
host regression built from the actual RX block completes 3 of 6 queued
packets before the fix and 6 of 6 after it. Single-ring, empty-mask and
two-poll budget cases pass. Descending priority is unchanged; this does
not establish fairness under sustained traffic.

Signed-off-by: John <dencity7 at gmail.com>

---
RFC validation and limits:

Source applicability and the host regression were checked against
backports 7.2 plus the 230 wireless patches from perceival/openwrt-flint3
commit 2365932733ca8ec3b346621d9cec2eb3df3b2cf3. The new patch applies
with zero fuzz. The same source-block regression and exact patch
application also pass against official ath.git main at
388d3c42e8aba1cfc3c6d2c52877a46d8cf740db (zero fuzz). No full module
build or hardware test was performed against either current revision.

Historical tests on Linux 6.18.39 with local backports 7.2-rc4/QCN6432
changes passed DHCP, DNS, 32 UDP flows and about 181 seconds of traffic
after reboot. These are bounded observations, not throughput or long-term
stability qualification. The contribution was developed with AI assistance.

--- a/drivers/net/wireless/ath/ath12k/wifi7/dp.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp.c
@@ -52,8 +52,10 @@
 			goto done;
 	}

-	if (dp->hw_params->ring_mask->rx[grp_id]) {
-		i = fls(dp->hw_params->ring_mask->rx[grp_id]) - 1;
+	ring_mask = dp->hw_params->ring_mask->rx[grp_id];
+	while (ring_mask) {
+		i = fls(ring_mask) - 1;
+		ring_mask &= ~BIT(i);
 		work_done = ath12k_wifi7_dp_rx_process(dp, i, napi, budget);
 		budget -= work_done;
 		tot_work_done += work_done;
-------------- next part --------------
From: John <dencity7 at gmail.com>
To: ath12k at lists.infradead.org
Cc: linux-wireless at vger.kernel.org
Subject: [RFC PATCH] wifi: ath12k: service all RX rings in an interrupt group
X-Unsent: 1
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

An RX interrupt group may select multiple receive rings. The Wi-Fi 7
handler currently services only the highest set bit, even when the NAPI
budget has room for work from another selected ring. Walk all selected
bits and retain the shared budget and existing early-exit behavior.

On a locally adapted GL-BE3600/QCN6432, group 5 selects bits 2 and 3. A
host regression built from the actual RX block completes 3 of 6 queued
packets before the fix and 6 of 6 after it. Single-ring, empty-mask and
two-poll budget cases pass. Descending priority is unchanged; this does
not establish fairness under sustained traffic.

Signed-off-by: John <dencity7 at gmail.com>

---
RFC validation and limits:

Source applicability and the host regression were checked against
backports 7.2 plus the 230 wireless patches from perceival/openwrt-flint3
commit 2365932733ca8ec3b346621d9cec2eb3df3b2cf3. The new patch applies
with zero fuzz. The same source-block regression and exact patch
application also pass against official ath.git main at
388d3c42e8aba1cfc3c6d2c52877a46d8cf740db (zero fuzz). No full module
build or hardware test was performed against either current revision.

Historical tests on Linux 6.18.39 with local backports 7.2-rc4/QCN6432
changes passed DHCP, DNS, 32 UDP flows and about 181 seconds of traffic
after reboot. These are bounded observations, not throughput or long-term
stability qualification. The contribution was developed with AI assistance.

--- a/drivers/net/wireless/ath/ath12k/wifi7/dp.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp.c
@@ -52,8 +52,10 @@
 			goto done;
 	}
 
-	if (dp->hw_params->ring_mask->rx[grp_id]) {
-		i = fls(dp->hw_params->ring_mask->rx[grp_id]) - 1;
+	ring_mask = dp->hw_params->ring_mask->rx[grp_id];
+	while (ring_mask) {
+		i = fls(ring_mask) - 1;
+		ring_mask &= ~BIT(i);
 		work_done = ath12k_wifi7_dp_rx_process(dp, i, napi, budget);
 		budget -= work_done;
 		tot_work_done += work_done;


More information about the ath12k mailing list