[PATCH v9] net: airoha: npu: use cacheline-sized buffers for mailbox DMA
From: Daniel Pawlik <hidden>
Date: 2026-08-18 06:22:13
Also in:
linux-arm-kernel, linux-mediatek
Subsystem:
airoha ethernet driver, networking drivers, the rest · Maintainers:
Lorenzo Bianconi, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
On EN7581 + MT7996 (Gemtek W1700K), mapping small caller buffers with
DMA_BIDIRECTIONAL regresses NPU version probe: the mailbox completes
successfully but WLAN_FUNC_GET_WAIT_NPU_VERSION reads as 0.0 instead of
0.1111.
Round mailbox payload allocations up to dma_get_cache_alignment() and
map the same rounded length with DMA_BIDIRECTIONAL while programming
the original payload length into the mailbox length register. On EN7581
the rounded map length is required for GET responses to be visible;
mapping only the payload size regresses probe back to 0.0.
Tested on Quantum Fiber / Gemtek W1700K (EN7581 + MT7996), kernel
6.18.44, including cold reboot.
Fixes: 6f884eb87a79 ("net: airoha: Fix DMA direction for NPU mailbox buffer")
Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260814110017.2795022-1-pawlik.dan@gmail.com/
Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260809152813.585797-1-pawlik.dan@gmail.com/
Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260805070851.2885888-1-pawlik.dan@gmail.com/
Assisted-by: Cursor:composer-2
Signed-off-by: Daniel Pawlik <redacted>
---
drivers/net/ethernet/airoha/airoha_npu.c | 25 +++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
index b679bed952de..9c95ddd7002e 100644
--- a/drivers/net/ethernet/airoha/airoha_npu.c
+++ b/drivers/net/ethernet/airoha/airoha_npu.c@@ -5,6 +5,7 @@ */ #include <linux/devcoredump.h> +#include <linux/dma-mapping.h> #include <linux/firmware.h> #include <linux/platform_device.h> #include <linux/of_net.h>
@@ -160,15 +161,21 @@ struct wlan_mbox_data { DECLARE_FLEX_ARRAY(u8, d); }; +static size_t airoha_npu_mbox_size(size_t len) +{ + return ALIGN(len, dma_get_cache_alignment()); +} + static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, void *p, int size) { u16 core = 0; /* FIXME */ u32 val, offset = core << 4; dma_addr_t dma_addr; + size_t map_len = airoha_npu_mbox_size(size); int ret; - dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL); + dma_addr = dma_map_single(npu->dev, p, map_len, DMA_BIDIRECTIONAL); ret = dma_mapping_error(npu->dev, dma_addr); if (ret) return ret;
@@ -191,7 +198,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, spin_unlock_bh(&npu->cores[core].lock); - dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL); + dma_unmap_single(npu->dev, dma_addr, map_len, DMA_BIDIRECTIONAL); return ret; }
@@ -333,7 +340,7 @@ static int airoha_npu_ppe_init(struct airoha_npu *npu) struct ppe_mbox_data *ppe_data; int err; - ppe_data = kzalloc_obj(*ppe_data); + ppe_data = kzalloc(airoha_npu_mbox_size(sizeof(*ppe_data)), GFP_KERNEL); if (!ppe_data) return -ENOMEM;
@@ -354,7 +361,7 @@ static int airoha_npu_ppe_deinit(struct airoha_npu *npu) struct ppe_mbox_data *ppe_data; int err; - ppe_data = kzalloc_obj(*ppe_data); + ppe_data = kzalloc(airoha_npu_mbox_size(sizeof(*ppe_data)), GFP_KERNEL); if (!ppe_data) return -ENOMEM;
@@ -375,7 +382,7 @@ static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu, struct ppe_mbox_data *ppe_data; int err; - ppe_data = kzalloc_obj(*ppe_data); + ppe_data = kzalloc(airoha_npu_mbox_size(sizeof(*ppe_data)), GFP_KERNEL); if (!ppe_data) return -ENOMEM;
@@ -399,7 +406,7 @@ static int airoha_npu_foe_commit_entry(struct airoha_npu *npu, struct ppe_mbox_data *ppe_data; int err; - ppe_data = kzalloc_obj(*ppe_data, GFP_ATOMIC); + ppe_data = kzalloc(airoha_npu_mbox_size(sizeof(*ppe_data)), GFP_ATOMIC); if (!ppe_data) return -ENOMEM;
@@ -434,7 +441,7 @@ static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu, int err, size = num_stats_entries * sizeof(*npu->stats); struct ppe_mbox_data *ppe_data; - ppe_data = kzalloc_obj(*ppe_data, GFP_ATOMIC); + ppe_data = kzalloc(airoha_npu_mbox_size(sizeof(*ppe_data)), GFP_ATOMIC); if (!ppe_data) return -ENOMEM;
@@ -466,7 +473,7 @@ static int airoha_npu_wlan_msg_send(struct airoha_npu *npu, int ifindex, int err, len; len = sizeof(*wlan_data) + data_len; - wlan_data = kzalloc(len, gfp); + wlan_data = kzalloc(airoha_npu_mbox_size(len), gfp); if (!wlan_data) return -ENOMEM;
@@ -489,7 +496,7 @@ static int airoha_npu_wlan_msg_get(struct airoha_npu *npu, int ifindex, int err, len; len = sizeof(*wlan_data) + data_len; - wlan_data = kzalloc(len, gfp); + wlan_data = kzalloc(airoha_npu_mbox_size(len), gfp); if (!wlan_data) return -ENOMEM;
--
2.55.0