[PATCH 4/4] b43: align DMA64 descriptor ring to 64K on AC cores

From: Alessio Ferri

Date: Wed Jun 17 2026 - 17:46:24 EST


From: Alessio Ferri <alessio.ferri.3012@xxxxxxxxx>

The AC d11 core (core_rev 40/42, BCM4352) exposes a 16-bit DMA descriptor
pointer (wrap mask 0xffff, not the 0x1fff b43 assumes). With an 8K-aligned
ring the engine wraps the pointer outside the ring and raises I_DE on RX.
Allocate the 64-bit ring with 64K size on these cores so the base is
64K-aligned and (base & 0xffff) == 0; dma_alloc_coherent() aligns to the
allocation size. ring_mem_size widens to u32 to hold 0x10000. N-PHY cores
report 0x1fff and keep the 8K allocation.

Assisted-by: claude:claude-Opus-4.8
Signed-off-by: Alessio Ferri <alessio.ferri@xxxxxxxxxxx>
---
drivers/net/wireless/broadcom/b43/dma.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
index 05da6987a845..cb308080312b 100644
--- a/drivers/net/wireless/broadcom/b43/dma.c
+++ b/drivers/net/wireless/broadcom/b43/dma.c
@@ -404,6 +404,18 @@ static inline
}
}

+static u32 b43_dma64_ringmem_size(struct b43_dmaring *ring)
+{
+ /* AC d11 cores (core_rev 40/42) expose a 16-bit descriptor pointer
+ * (mask 0xffff) and need a 64K-aligned ring; dma_alloc_coherent()
+ * aligns to the (power-of-2) allocation size. Smaller cores use the
+ * 0x1fff mask and are fine with 8K.
+ */
+ if (ring->dev->dev->core_rev == 40 || ring->dev->dev->core_rev == 42)
+ return 0x10000;
+ return B43_DMA64_RINGMEMSIZE;
+}
+
static int alloc_ringmemory(struct b43_dmaring *ring)
{
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
@@ -415,8 +427,8 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
* B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use
* more than 256 slots for ring.
*/
- u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
- B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+ u32 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ b43_dma64_ringmem_size(ring) : B43_DMA32_RINGMEMSIZE;

ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
ring_mem_size, &(ring->dmabase),
@@ -429,8 +441,8 @@ static int alloc_ringmemory(struct b43_dmaring *ring)

static void free_ringmemory(struct b43_dmaring *ring)
{
- u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
- B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+ u32 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ b43_dma64_ringmem_size(ring) : B43_DMA32_RINGMEMSIZE;
dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size,
ring->descbase, ring->dmabase);
}

--
2.54.0