From: Alessio Ferri <alessio.ferri@mythread.it>
To: Andreas Wendleder <gonsolo@gmail.com>
Cc: linux-wireless@vger.kernel.org,
Johannes Berg <johannes@sipsolutions.net>,
b43-dev@lists.infradead.org, Michael Buesch <m@bues.ch>,
kvalo@kernel.org, julian.calaby@gmail.com, jpeisach@ubuntu.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH wireless-next 2/2] wifi: b43: handle 64-bit DMA engines whose index registers hold bus addresses
Date: Tue, 27 Oct 2026 20:24:24 +0100 [thread overview]
Message-ID: <20261027202424.7ae292c7@fedora> (raw)
In-Reply-To: <20261014143225.82149-3-gonsolo@gmail.com>
Il giorno Wed, 14 Oct 2026 16:32:25 +0200
Andreas Wendleder <gonsolo@gmail.com> ha scritto:
> Newer 64-bit DMA engines (found on the core revisions of the BCM4352
> and BCM4360) accept ring addresses with low bits set and then use bus
> addresses, not offsets into the ring, in the index and status
> registers. They are detected as brcmsmac does it in
> _dma_descriptor_align(): write 0xff0 to TXRINGLO and see whether it
> sticks.
>
> On such an engine keep the ring address in the new ring->ptr_base,
> add it when writing TXINDEX and RXINDEX and subtract it when reading
> RXSTATUS. The ring address registers have to be written before the
> control word enables the engine, and the hardware defaults of burst
> length, outstanding reads and prefetch control (the *CTL_KEEP masks)
> have to be preserved.
>
> Engines that keep offsets behave as before.
>
> Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
> ---
> drivers/net/wireless/broadcom/b43/b43.h | 1 +
> drivers/net/wireless/broadcom/b43/dma.c | 52
> +++++++++++++++++++------ drivers/net/wireless/broadcom/b43/dma.h |
> 3 ++ 3 files changed, 45 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/broadcom/b43/b43.h
> b/drivers/net/wireless/broadcom/b43/b43.h index c0d8fc0..e1e8083
> 100644 --- a/drivers/net/wireless/broadcom/b43/b43.h
> +++ b/drivers/net/wireless/broadcom/b43/b43.h
> @@ -668,6 +668,7 @@ struct b43_dma {
> u32 translation; /* Routing bits */
> bool translation_in_low; /* Should translation bit go into
> low addr? */ bool parity; /* Check for parity */
> + bool ptr_is_addr;
> };
>
> struct b43_pio_txqueue;
> diff --git a/drivers/net/wireless/broadcom/b43/dma.c
> b/drivers/net/wireless/broadcom/b43/dma.c index 05da698..20d910a
> 100644 --- a/drivers/net/wireless/broadcom/b43/dma.c
> +++ b/drivers/net/wireless/broadcom/b43/dma.c
> @@ -212,7 +212,7 @@ static void op64_fill_descriptor(struct
> b43_dmaring *ring,
> static void op64_poke_tx(struct b43_dmaring *ring, int slot)
> {
> - b43_dma_write(ring, B43_DMA64_TXINDEX,
> + b43_dma_write(ring, B43_DMA64_TXINDEX, ring->ptr_base +
> (u32) (slot * sizeof(struct b43_dmadesc64)));
> }
>
> @@ -233,14 +233,15 @@ static int op64_get_current_rxslot(struct
> b43_dmaring *ring) u32 val;
>
> val = b43_dma_read(ring, B43_DMA64_RXSTATUS);
> - val &= B43_DMA64_RXSTATDPTR;
> + val = ((val & B43_DMA64_RXSTATDPTR) - ring->ptr_base) &
> + B43_DMA64_RXSTATDPTR;
>
> return (val / sizeof(struct b43_dmadesc64));
> }
>
> static void op64_set_current_rxslot(struct b43_dmaring *ring, int
> slot) {
> - b43_dma_write(ring, B43_DMA64_RXINDEX,
> + b43_dma_write(ring, B43_DMA64_RXINDEX, ring->ptr_base +
> (u32) (slot * sizeof(struct b43_dmadesc64)));
> }
>
> @@ -690,9 +691,19 @@ static int dmacontroller_setup(struct
> b43_dmaring *ring) & B43_DMA64_TXADDREXT_MASK;
> if (!parity)
> value |= B43_DMA64_TXPARITYDISABLE;
> - b43_dma_write(ring, B43_DMA64_TXCTL, value);
> - b43_dma_write(ring, B43_DMA64_TXRINGLO,
> addrlo);
> - b43_dma_write(ring, B43_DMA64_TXRINGHI,
> addrhi);
> + if (ring->dev->dma.ptr_is_addr) {
> + ring->ptr_base =
> lower_32_bits(ring->dmabase);
> + value |= b43_dma_read(ring,
> B43_DMA64_TXCTL) &
> + B43_DMA64_TXCTL_KEEP;
> + b43_dma_write(ring,
> B43_DMA64_TXRINGLO, addrlo);
> + b43_dma_write(ring,
> B43_DMA64_TXRINGHI, addrhi);
> + b43_dma_write(ring, B43_DMA64_TXCTL,
> value);
> + } else {
> + ring->ptr_base = 0;
> + b43_dma_write(ring, B43_DMA64_TXCTL,
> value);
> + b43_dma_write(ring,
> B43_DMA64_TXRINGLO, addrlo);
> + b43_dma_write(ring,
> B43_DMA64_TXRINGHI, addrhi);
> + }
> } else {
> u32 ringbase = (u32) (ring->dmabase);
> addrext = b43_dma_address(&ring->dev->dma,
> ringbase, B43_DMA_ADDR_EXT); @@ -722,11 +733,21 @@ static int
> dmacontroller_setup(struct b43_dmaring *ring) &
> B43_DMA64_RXADDREXT_MASK; if (!parity)
> value |= B43_DMA64_RXPARITYDISABLE;
> - b43_dma_write(ring, B43_DMA64_RXCTL, value);
> - b43_dma_write(ring, B43_DMA64_RXRINGLO,
> addrlo);
> - b43_dma_write(ring, B43_DMA64_RXRINGHI,
> addrhi);
> - b43_dma_write(ring, B43_DMA64_RXINDEX,
> ring->nr_slots *
> - sizeof(struct b43_dmadesc64));
> + if (ring->dev->dma.ptr_is_addr) {
> + ring->ptr_base =
> lower_32_bits(ring->dmabase);
> + value |= b43_dma_read(ring,
> B43_DMA64_RXCTL) &
> + B43_DMA64_RXCTL_KEEP;
> + b43_dma_write(ring,
> B43_DMA64_RXRINGLO, addrlo);
> + b43_dma_write(ring,
> B43_DMA64_RXRINGHI, addrhi);
> + b43_dma_write(ring, B43_DMA64_RXCTL,
> value);
> + } else {
> + ring->ptr_base = 0;
> + b43_dma_write(ring, B43_DMA64_RXCTL,
> value);
> + b43_dma_write(ring,
> B43_DMA64_RXRINGLO, addrlo);
> + b43_dma_write(ring,
> B43_DMA64_RXRINGHI, addrhi);
> + }
> + b43_dma_write(ring, B43_DMA64_RXINDEX,
> ring->ptr_base +
> + ring->nr_slots * sizeof(struct
> b43_dmadesc64)); } else {
> u32 ringbase = (u32) (ring->dmabase);
> addrext = b43_dma_address(&ring->dev->dma,
> ringbase, B43_DMA_ADDR_EXT); @@ -1080,6 +1101,15 @@ int
> b43_dma_init(struct b43_wldev *dev) dma->parity = false;
> #endif
>
> + dma->ptr_is_addr = false;
> + if (type == B43_DMA_64BIT) {
> + u16 ringlo = b43_dmacontroller_base(type, 0) +
> B43_DMA64_TXRINGLO; +
> + b43_write32(dev, ringlo, 0xff0);
> + dma->ptr_is_addr = b43_read32(dev, ringlo) != 0;
> + b43_write32(dev, ringlo, 0);
> + }
> +
> err = -ENOMEM;
> /* setup TX DMA channels. */
> dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
> diff --git a/drivers/net/wireless/broadcom/b43/dma.h
> b/drivers/net/wireless/broadcom/b43/dma.h index f9f65bb..eddc882
> 100644 --- a/drivers/net/wireless/broadcom/b43/dma.h
> +++ b/drivers/net/wireless/broadcom/b43/dma.h
> @@ -90,6 +90,7 @@ struct b43_dmadesc32 {
> #define B43_DMA64_TXPARITYDISABLE
> 0x00000800 #define B43_DMA64_TXADDREXT_MASK
> 0x00030000 #define
> B43_DMA64_TXADDREXT_SHIFT 16 +#define
> B43_DMA64_TXCTL_KEEP 0x03FC00C0
> #define B43_DMA64_TXINDEX 0x04 #define
> B43_DMA64_TXRINGLO 0x08 #define
> B43_DMA64_TXRINGHI 0x0C @@ -118,6
> +119,7 @@ struct b43_dmadesc32 { #define
> B43_DMA64_RXPARITYDISABLE 0x00000800 #define
> B43_DMA64_RXADDREXT_MASK 0x00030000
> #define B43_DMA64_RXADDREXT_SHIFT 16
> +#define B43_DMA64_RXCTL_KEEP
> 0x03FC0000 #define B43_DMA64_RXINDEX
> 0x24 #define B43_DMA64_RXRINGLO 0x28
> #define B43_DMA64_RXRINGHI 0x2C @@
> -235,6 +237,7 @@ struct b43_dmaring { u8 *txhdr_cache;
> /* (Unadjusted) DMA base bus-address of the ring memory. */
> dma_addr_t dmabase;
> + u32 ptr_base;
> /* Number of descriptor slots in the ring. */
> int nr_slots;
> /* Number of used descriptor slots. */
Tested on DSL 3580L, with 4352 chip on 5Ghz, the chip transmit and no
dma error arise. Without the patch the dma engine report an error on
the descriptor. Earlier in June i wrongly asserted that the DMA on AC
chips was needing 64 Kb segments, it was a wrong conclusion: going 64kb
did stop the error, but for the wrong reason.
Tested-by: Alessio Ferri <alessio.ferri@mythread.it>
prev parent reply other threads:[~2026-10-27 19:24 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 14:32 [PATCH wireless-next 0/2] wifi: b43: MAC filter and 64-bit DMA fixes for the BCM4360 Andreas Wendleder
2026-10-14 14:32 ` [PATCH wireless-next 1/2] wifi: b43: reprogram the MAC filter after an interface restart Andreas Wendleder
2026-10-27 19:21 ` Alessio Ferri
2026-10-27 19:25 ` Alessio Ferri
2026-10-27 19:27 ` Alessio Ferri
2026-10-14 14:32 ` [PATCH wireless-next 2/2] wifi: b43: handle 64-bit DMA engines whose index registers hold bus addresses Andreas Wendleder
2026-10-27 19:24 ` Alessio Ferri [this message]
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=20261027202424.7ae292c7@fedora \
--to=alessio.ferri@mythread.it \
--cc=b43-dev@lists.infradead.org \
--cc=gonsolo@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=jpeisach@ubuntu.com \
--cc=julian.calaby@gmail.com \
--cc=kvalo@kernel.org \
--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®