From: Marco Martins <marcomartins86@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: "Johannes Berg" <johannes@sipsolutions.net>,
"Michael Büsch" <m@bues.ch>,
b43-dev@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH wireless-next] wifi: b43: fix missing beacons by starting at the next TBTT
Date: Mon, 2 Nov 2026 23:59:39 +0000 [thread overview]
Message-ID: <20261102235939.156522-1-marcomartins86@gmail.com> (raw)
b43_set_beacon_int() programs the first TBTT one beacon interval after
zero, as if the TSF started there. The hardware compares it with the
low 32 bits of the TSF. Up to 2^31 us past it, it moves it on by whole
intervals and beacons. Further past, it leaves it and sends no beacons:
on a BCM5352 (core rev 9, firmware 666) the TBTT stayed at 0x19000 for
over six minutes while the low 32 bits of the TSF ran from 0xd1d508fa
to 0xe7f71356.
Without beacons there are no DTIMs, so the frames held in the multicast
ring for stations in power save are never sent. The ring fills and b43
stops the queue of the frame that filled it, best effort for most
broadcasts: stations still associate, but get no DHCP lease.
The TSF is not reset when beaconing starts, so an AP that starts with
the low 32 bits of the TSF in the upper half of their range does not
beacon. With one interface, starting the radio resets the TSF, so this
needs beaconing to start again while the radio stays up, or a TSF taken
from other stations in IBSS or mesh mode. The first was tested: hostapd
stopped and started again on an interface it had found up, which it
leaves up, with the TSF set to 50 minutes in between by b43_tsf_write().
The TBTT stayed at 0x19000 and no TBTT interrupt came for over 20
seconds; with this patch the TBTT was just ahead of the TSF and the
interrupts went on. IBSS and mesh were not tested.
This was found with an out-of-tree patch that runs a station and an AP
on one b43 radio, as a repeater: the station interface keeps the radio
up and synchronises the TSF to its AP, and an AP restarted beside it did
not beacon whenever it started in that half. With this patch it did, in
the same half.
Where the hardware does move the TBTT on, the beacons go out at
multiples of the interval in the low 32 bits only, which are not the
TBTTs once the TSF has passed 2^32 us: 2^32 us is 4 TU more than a
multiple of 100 TU, so they are 4 TU off for every 2^32 us the TSF had
run when beaconing started.
Program the next TBTT from the TSF instead, as ath5k does.
The bug was found, and this patch and its description written, with an
AI coding assistant (Claude Code, model Claude Opus 5.5), asked to find
why phones got no DHCP lease from the repeater after its AP restarted.
It read b43 and mac80211, added debug hooks to b43 that dump the TSF,
the TBTT registers and the DMA rings, and ran the tests on the device.
Fixes: a82d992261f7 ("b43: Beaconing fixes")
Signed-off-by: Marco Martins <marcomartins86@gmail.com>
---
Tested on an ASUS WL-320gE (BCM5352) running OpenWrt 25.12 (backports
6.18, built for MIPS without warnings) with the out-of-tree station and
AP patch: as a repeater, and as a plain AP with one interface.
Not done: no build or run of wireless-next or mainline itself, only of
the same function in backports 6.18; IBSS and mesh not tested; the
single-interface test set the TSF with a debug hook instead of waiting
50 minutes; beaconing resuming when the low 32 bits of the TSF wrap
around was not observed.
drivers/net/wireless/broadcom/b43/main.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 3825b6a..5fa3cd9 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -1852,10 +1852,22 @@ static void b43_update_templates(struct b43_wl *wl)
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
+ u64 tsf;
+ u32 rem;
+
b43_time_lock(dev);
if (dev->dev->core_rev >= 3) {
+ /* Start at the next TBTT, the next multiple of the beacon
+ * interval on the TSF. The TSF need not be near zero, and the
+ * hardware sends no beacons for a start more than 2^31 us
+ * behind it.
+ */
+ b43_tsf_read(dev, &tsf);
+ tsf >>= 10;
+ div_u64_rem(tsf, beacon_int, &rem);
+ tsf += beacon_int - rem;
b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
- b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
+ b43_write32(dev, B43_MMIO_TSF_CFP_START, lower_32_bits(tsf << 10));
} else {
b43_write16(dev, 0x606, (beacon_int >> 6));
b43_write16(dev, 0x610, beacon_int);
base-commit: 991a73f4909f1348ffb4b38765cdb522a775e4c2
--
2.53.0
reply other threads:[~2026-11-03 0:02 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261102235939.156522-1-marcomartins86@gmail.com \
--to=marcomartins86@gmail.com \
--cc=b43-dev@lists.infradead.org \
--cc=johannes@sipsolutions.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=m@bues.ch \
/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
all inboxes | Powered by JetHome®