[PATCH v8] net: airoha: npu: use cacheline-sized buffers for mailbox DMA

Daniel Pawlik pawlik.dan at gmail.com
Wed Aug 19 05:27:33 PDT 2026


Hi,

I instrumented airoha_npu_send_msg() on EN7581 (Gemtek W1700K) with
DMA_BIDIRECTIONAL and the original unaligned 24-byte payload. Here is
what I found.

1) Every dma_map_single() call lands in swiotlb bounce buffers.
   The driver only calls dma_set_coherent_mask(DMA_BIT_MASK(32)) at
   probe but never calls dma_set_mask(). On this non-coherent ARM64
   platform that appears to force all streaming DMA through swiotlb.

2) The NPU permanently hangs after ~41 mailbox calls.
   The first 41 PPE SRAM-init calls succeed (mbox_status=0x7, ~10ms
   each). Starting at the 42nd, the NPU never sets the DONE bit —
   every subsequent call times out at 100ms (ret=-110,
   mbox_status=0x1), including the WLAN version query that triggers
   the "failed getting NPU fw version" probe failure.

3) Response data is never synced back through the bounce buffer.
   post-sync and post-unmap hex dumps are byte-identical to pre-map
   for both successful and timed-out calls.

4) Buffer pointer is 64-byte aligned (p_aligned=1), size is 24
   (sub-cacheline, cache_align=64). The swiotlb slot size is 2048,
   so the bounce buffer itself is always page-aligned.

5) dma_alloc_coherent mappings (shown by DMA-API debug dump) map
   P==D at addresses around 0x91xxxxxx, bypassing swiotlb entirely.
   The mailbox works reliably through that path.

Representative trace (last success / first failure):

  [19.541] func_id=0 p=...dfc0 size=24 cache_align=64 p_aligned=1
  [19.545] mapped: dma=0xff765000 dma_aligned=1 is_swiotlb=1
  [19.541] mbox done: ret=0 mbox_status=0x7      <-- last success

  [19.588] func_id=0 p=...dfc0 size=24 cache_align=64 p_aligned=1
  [19.618] mapped: dma=0xff765800 dma_aligned=1 is_swiotlb=1
  [19.728] mbox done: ret=-110 mbox_status=0x1    <-- first timeout
  (all subsequent calls also timeout, NPU never recovers)

My working theory is that the missing dma_set_mask() is the root cause.
Without it the kernel bounces every streaming mapping through swiotlb,
and either the bounce-buffer sync path on this non-coherent platform
has a bug with sub-cacheline transfers, or the NPU firmware cannot
handle the latency/address-range change that bouncing introduces.

I plan to test next with dma_set_mask_and_coherent(DMA_BIT_MASK(32))
to see whether that eliminates the swiotlb bounce and restores the
mailbox. If it does, that narrows the bug to either the swiotlb sync
implementation or the platform DMA ops for non-coherent devices.

Debug instrumentation patch (applied on top of OpenWrt's 6.18.44):
https://github.com/openwrt/openwrt/commit/13ea79d9a411dc497882e820e4c881443457bd97

Full dmesg from the instrumented boot:
https://gist.github.com/danpawlik/b351e8a06218a3aaf68a2cb31a32ea8f

Thanks for help,
Dan


wt., 18 sie 2026 o 17:29 Jakub Kicinski <kuba at kernel.org> napisał(a):
>
> On Tue, 18 Aug 2026 08:23:33 +0200 Daniel Pawlik wrote:
> > v8 does not switch to coherent DMA; it only rounds up mailbox payload
> > allocations (dma_get_cache_alignment() in v9) and maps the same rounded
> > length with DMA_BIDIRECTIONAL, while the mailbox length register still
> > uses the original payload size. On this board, mapping only the payload
> > size regresses probe back to 0.0 even with the larger allocation, so the
> > rounded map length seems required here.
>
> Please trace into the dma API implementation on this platform where the
> alignment makes a difference. The "unaligned length" path must be buggy.
> We should fix it there, not in all the drivers (my concern being that
> this is not the only driver that hits the issue).



--
Z poważaniem,
Daniel Pawlik



More information about the Linux-mediatek mailing list