From: Shivesh <chanelshivesh@gmail.com>
To: arend.vanspriel@broadcom.com
Cc: linux-wireless@vger.kernel.org, brcm80211@lists.linux.dev,
brcm80211-dev-list.pdl@broadcom.com,
linux-kernel@vger.kernel.org, Shivesh <shivesh@example.com>
Subject: [PATCH 5/8] wifi: brcmfmac: msgbuf: tune thresholds and optimize sleep latency
Date: Thu, 30 Jul 2026 16:03:53 +0000 [thread overview]
Message-ID: <20260730160425.11933-5-shivesh@example.com> (raw)
In-Reply-To: <20260730160425.11933-1-shivesh@example.com>
Increases tx pktids and tune flush thresholds. Fixes a silent tx stall
under high load by correctly using test_and_set_bit. Optimizes
initialization polling latency from msleep(10) to usleep_range.
Signed-off-by: Shivesh <shivesh@example.com>
---
.../broadcom/brcm80211/brcmfmac/msgbuf.c | 69 ++++++++++++++++---
1 file changed, 61 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index ba1ce1552e0f..8db6167072da 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -48,7 +48,19 @@
#define MSGBUF_TYPE_LPBK_DMAXFER 0x13
#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT 0x14
-#define NR_TX_PKTIDS 2048
+/*
+ * NR_TX_PKTIDS: number of simultaneously in-flight TX packet IDs.
+ * Each outstanding TX frame consumes one ID until the dongle returns
+ * a TX-status completion. The original 2048-entry pool exhausted under
+ * ≥4 concurrent iperf3 streams on Wi-Fi 5/6 (802.11ac/ax) devices,
+ * causing "No PKTID available" drops and TCP retransmits. 4096 gives
+ * headroom for high-aggregation scenarios while still fitting in a
+ * modest amount of host memory (~48 KB for the pktid table entries).
+ *
+ * NR_RX_PKTIDS: RX post buffers pre-allocated to the dongle. 1024 is
+ * sufficient for current hardware RX ring depths; leave unchanged.
+ */
+#define NR_TX_PKTIDS 4096
#define NR_RX_PKTIDS 1024
#define BRCMF_IOCTL_REQ_PKTID 0xFFFE
@@ -64,8 +76,29 @@
#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK 0x07
#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
-#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
-#define BRCMF_MSGBUF_TX_FLUSH_CNT2 96
+/*
+ * TX flush / doorbell-ring thresholds.
+ *
+ * CNT1 is the minimum number of frames to accumulate in the commonring
+ * before the first intermediate write_complete() (doorbell ring) is
+ * issued mid-batch. CNT2 is the hard flush interval: after this many
+ * frames have been written since the last flush, we unconditionally
+ * ring the bell and reset the counter.
+ *
+ * Raising both from the original 32/96 to 64/128 doubles the average
+ * number of TX descriptors committed per MMIO write, halving the PCIe
+ * doorbell rate on sustained throughput workloads. The tradeoff is a
+ * marginally higher worst-case latency for the last frames in a burst,
+ * which in practice is hidden by the time the dongle DMA engine drains
+ * the previous batch.
+ *
+ * TRICKLE_TXWORKER_THRS governs how often brcmf_msgbuf_tx_queue_data()
+ * forces a workqueue schedule when the queue depth is not a multiple of
+ * this value. Keeping it at half of CNT1 (32) preserves responsiveness
+ * for low-rate flows (e.g. VoIP, ICMP) that never accumulate 64 frames.
+ */
+#define BRCMF_MSGBUF_TX_FLUSH_CNT1 64
+#define BRCMF_MSGBUF_TX_FLUSH_CNT2 128
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
@@ -787,10 +820,30 @@ static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,
{
struct brcmf_commonring *commonring;
- set_bit(flowid, msgbuf->flow_map);
+ /*
+ * If the bit was already set, a txflow_work item is already
+ * queued or running for this ring. In that case the existing
+ * worker will drain our freshly enqueued frame when it runs,
+ * so we only need to schedule another work item when the
+ * force flag is set or the ring is below the delay threshold.
+ *
+ * If the bit was NOT set (test_and_set_bit returns false), no
+ * worker is pending for this ring at all. We MUST schedule
+ * one unconditionally, otherwise the frame we just enqueued
+ * will sit in the flowring unsent until some unrelated event
+ * triggers the workqueue — causing silent TX stalls under
+ * high load when outstanding_tx >= DELAY_TXWORKER_THRS.
+ */
+ if (!test_and_set_bit(flowid, msgbuf->flow_map)) {
+ /* Bit was clear: no worker pending, always schedule. */
+ queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+ return 0;
+ }
+
+ /* Bit was already set: worker pending, apply coalescing heuristic. */
commonring = msgbuf->flowrings[flowid];
- if ((force) || (atomic_read(&commonring->outstanding_tx) <
- BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
+ if (force || (atomic_read(&commonring->outstanding_tx) <
+ BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
return 0;
@@ -1621,11 +1674,11 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
do {
brcmf_msgbuf_rxbuf_data_fill(msgbuf);
if (msgbuf->max_rxbufpost != msgbuf->rxbufpost)
- msleep(10);
+ usleep_range(1000, 2000);
else
break;
count++;
- } while (count < 10);
+ } while (count < 100);
brcmf_msgbuf_rxbuf_event_post(msgbuf);
brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
--
2.53.0
next prev parent reply other threads:[~2026-07-30 16:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-30 16:03 [PATCH 1/8] wifi: brcmfmac: flowring: replace O(N) loop with atomic counter Shivesh
2026-07-30 16:03 ` [PATCH 2/8] wifi: brcmfmac: sdio: coalesce host locks in rx path Shivesh
2026-07-30 16:03 ` [PATCH 3/8] wifi: brcmfmac: core: populate radiotap header with RSSI Shivesh
2026-07-30 16:03 ` [PATCH 4/8] wifi: brcmfmac: cfg80211: implement PMKID_V2 and fix delay busy-wait Shivesh
2026-07-30 16:03 ` Shivesh [this message]
2026-07-30 16:03 ` [PATCH 6/8] wifi: brcmfmac: pcie: optimize latency and irq teardown Shivesh
2026-07-30 16:03 ` [PATCH 7/8] wifi: brcmfmac: fwsignal: safe no-op on duplicate MAC add Shivesh
2026-07-30 16:03 ` [PATCH 8/8] wifi: brcmsmac: ampdu: clarify standard compliance on QoS change Shivesh
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=20260730160425.11933-5-shivesh@example.com \
--to=chanelshivesh@gmail.com \
--cc=arend.vanspriel@broadcom.com \
--cc=brcm80211-dev-list.pdl@broadcom.com \
--cc=brcm80211@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=shivesh@example.com \
/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;
as well as URLs for NNTP newsgroup(s).