* [RFC net-next 0/3] net: airoha: npu: keep NPU-shared DMA buffers in the NPU window
@ 2026-10-24 15:41 Chris Scott
2026-10-24 15:41 ` [RFC net-next 1/3] dt-bindings: net: airoha: npu: add DMA pool memory region Chris Scott
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Chris Scott @ 2026-10-24 15:41 UTC (permalink / raw)
To: netdev
Cc: lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni, robh,
krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
pawlik.dan, zhengping.zhang, Chris Scott
The EN7581 NPU can only address host DRAM at 0x80000000-0xbfffffff;
higher addresses alias the lower 1 GiB, as confirmed by Airoha [1].
On boards with 2 GiB of RAM nothing keeps the buffers the NPU reads
and writes inside that window:
- the mailbox buffers are streaming-mapped kzalloc() memory, which on
arm64 bounces through swiotlb; on W1700K the swiotlb pool is at
0xff6cf000, so the NPU version query reads back 0.0 and mt76 does not
bind NPU offload (this is the issue behind the earlier "use coherent
DMA for mailbox messages" / cacheline-buffer postings [2]);
- the coherent buffers mt76 allocates on the NPU device (NPU TX/RX
rings, HW-RRO and TXD buffers) currently land in the window only
because of early-boot allocation order; reserving low DRAM away makes
the SoC hang right after mt7996 firmware load.
Patch 1 adds an optional "dma" shared-dma-pool region to the NPU
binding. Patch 2 attaches it as the NPU device coherent pool, so every
coherent allocation on the NPU device comes from the window. Patch 3
moves the mailbox to per-core coherent buffers, which then come from
that pool.
Streaming mappings are deliberately left alone. Packet buffers are only
passed through to the WiFi DMA engine; restricting them with a
restricted-dma-pool or a bus DMA limit forces swiotlb bouncing and cost
~22% of host-path WiFi TX in testing, and the default swiotlb pool is
itself outside the window on these boards.
Sent as RFC while net-next is closed; I will repost as v1 once it
reopens. Feedback on the approach is welcome, in particular whether a
reserved coherent pool is the preferred way to express the NPU window
rather than a dma-ranges based limit.
Testing: Daniel tested this series, backported to OpenWrt kernel
6.18.57, on a Gemtek W1700K (EN7581 + MT7996, 2 GiB) with a 16 MiB
pool: the pool is assigned at 0xbf000000-0xbfffffff, the NPU version
query is correct, all three bands and MLO come up and there are no
warnings. I tested the equivalent of patches 2 and 3 on the same board
with 6.18.55 and 7.3-rc6: all mt76 NPU rings/RRO/TXD buffers come from
the pool (~10.7 MiB used), host-path and offloaded WiFi throughput are
unchanged versus no pool, and boot still succeeds with low DRAM
reserved away. On net-next the series was build-tested with W=1
(airoha and mt76 incl. MT7996_NPU, at each patch), checkpatch --strict
and dt_binding_check.
mainline en7581.dtsi does not have an NPU node yet, so there is no DTS
change here; boards using the WLAN offload need a 16 MiB pool, others
only need the mailbox (1 MiB is plenty).
Tools: patch 1 was originally written with Codex and patch 3 with
Cursor; patch 2 was written with Claude (Anthropic), which was also
used to rebase patches 1 and 3 onto net-next and rewrite their commit
messages.
[1] https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com
[2] https://lore.kernel.org/r/20260809152813.585797-1-pawlik.dan@gmail.com
Chris Scott (1):
net: airoha: npu: attach a coherent pool in the NPU window
Daniel Pawlik (2):
dt-bindings: net: airoha: npu: add DMA pool memory region
net: airoha: npu: use coherent memory for mailbox messages
.../bindings/net/airoha,en7581-npu.yaml | 40 +++++----
drivers/net/ethernet/airoha/airoha_npu.c | 83 +++++++++++++++----
include/linux/soc/airoha/airoha_offload.h | 3 +
3 files changed, 95 insertions(+), 31 deletions(-)
base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [RFC net-next 1/3] dt-bindings: net: airoha: npu: add DMA pool memory region 2026-10-24 15:41 [RFC net-next 0/3] net: airoha: npu: keep NPU-shared DMA buffers in the NPU window Chris Scott @ 2026-10-24 15:41 ` Chris Scott 2026-10-24 15:41 ` [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window Chris Scott 2026-10-24 15:41 ` [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages Chris Scott 2 siblings, 0 replies; 6+ messages in thread From: Chris Scott @ 2026-10-24 15:41 UTC (permalink / raw) To: netdev Cc: lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno, devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, pawlik.dan, zhengping.zhang, Chris Scott From: Daniel Pawlik <pawlik.dan@gmail.com> The EN7581 NPU can only address host DRAM at 0x80000000-0xbfffffff; higher addresses alias the lower 1 GiB. Allow an optional shared DMA pool, after the firmware region or after the WLAN regions, so coherent buffers shared with the NPU can be kept inside that window. The firmware region stays first for existing users. The original version of this patch was written with Codex; it was rebased onto net-next and its commit message rewritten with Claude (Anthropic). Link: https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com Signed-off-by: Daniel Pawlik <pawlik.dan@gmail.com> Signed-off-by: Chris Scott <gilroyscott1970@gmail.com> --- .../bindings/net/airoha,en7581-npu.yaml | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/net/airoha,en7581-npu.yaml b/Documentation/devicetree/bindings/net/airoha,en7581-npu.yaml index aefa19c5b4..21a1a27500 100644 --- a/Documentation/devicetree/bindings/net/airoha,en7581-npu.yaml +++ b/Documentation/devicetree/bindings/net/airoha,en7581-npu.yaml @@ -42,22 +42,34 @@ properties: - description: wlan irq line5 memory-region: - items: - - description: NPU firmware binary region - - description: NPU wlan offload RX buffers region - - description: NPU wlan offload TX buffers region - - description: NPU wlan offload TX packet identifiers region - - description: NPU wlan Block Ack buffers region - minItems: 1 + oneOf: + - items: + - description: NPU firmware binary region + - description: Coherent DMA pool for buffers shared with the NPU + minItems: 1 + - items: + - description: NPU firmware binary region + - description: NPU wlan offload RX buffers region + - description: NPU wlan offload TX buffers region + - description: NPU wlan offload TX packet identifiers region + - description: NPU wlan Block Ack buffers region + - description: Coherent DMA pool for buffers shared with the NPU + minItems: 4 memory-region-names: - items: - - const: firmware - - const: pkt - - const: tx-pkt - - const: tx-bufid - - const: ba - minItems: 1 + oneOf: + - items: + - const: firmware + - const: dma + minItems: 1 + - items: + - const: firmware + - const: pkt + - const: tx-pkt + - const: tx-bufid + - const: ba + - const: dma + minItems: 4 firmware-name: items: -- 2.53.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window 2026-10-24 15:41 [RFC net-next 0/3] net: airoha: npu: keep NPU-shared DMA buffers in the NPU window Chris Scott 2026-10-24 15:41 ` [RFC net-next 1/3] dt-bindings: net: airoha: npu: add DMA pool memory region Chris Scott @ 2026-10-24 15:41 ` Chris Scott 2026-10-26 7:48 ` Lorenzo Bianconi 2026-10-24 15:41 ` [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages Chris Scott 2 siblings, 1 reply; 6+ messages in thread From: Chris Scott @ 2026-10-24 15:41 UTC (permalink / raw) To: netdev Cc: lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno, devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, pawlik.dan, zhengping.zhang, Chris Scott The EN7581 NPU can only address host DRAM at 0x80000000-0xbfffffff; higher addresses alias the lower 1 GiB. The coherent buffers allocated on the NPU device are all shared with the NPU: since mt76 uses the NPU device as dma_dev, these are the NPU TX/RX descriptor rings, the HW-RRO ba_bitmap/addr_elem/msdu_pg/session buffers and the NPU TXD buffers. On a 2 GiB board nothing keeps them below 0xc0000000; they normally land there only because of early-boot allocation order. With low DRAM reserved away on W1700K the SoC hangs right after mt7996 firmware load. If the NPU node has an optional "dma" reserved-memory region, attach it as the device coherent pool so all of these come from the window. The next patch moves the mailbox buffers to coherent memory as well. Unlike a restricted-dma-pool this leaves streaming mappings alone. Packet buffers are passed through to the WiFi DMA engine: on W1700K with 96% of TX skbs and ~20% of RX page_pool buffers above 0xc0000000, host-path traffic and sha256 file round-trips stay intact, at the same throughput as without a pool, whereas a restricted-dma-pool (swiotlb bouncing) costs ~22% of host-path TX. A device coherent pool has no fallback once full; mt76 and the mailbox use ~10.7 MiB with MT7996, so the DT region should be 16 MiB. This patch was written with the help of Claude (Anthropic, claude- opus-5-5). Link: https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com Tested-by: Daniel Pawlik <pawlik.dan@gmail.com> Signed-off-by: Chris Scott <gilroyscott1970@gmail.com> --- drivers/net/ethernet/airoha/airoha_npu.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index 4d3195eb00..069fd60680 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -693,6 +693,11 @@ static const struct regmap_config regmap_config = { .disable_locking = true, }; +static void airoha_npu_rmem_release(void *data) +{ + of_reserved_mem_device_release(data); +} + static int airoha_npu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -776,6 +781,19 @@ static int airoha_npu_probe(struct platform_device *pdev) if (err) return err; + if (of_property_match_string(dev->of_node, "memory-region-names", + "dma") >= 0) { + err = of_reserved_mem_device_init_by_name(dev, dev->of_node, + "dma"); + if (err) + return err; + + err = devm_add_action_or_reset(dev, airoha_npu_rmem_release, + dev); + if (err) + return err; + } + err = airoha_npu_run_firmware(dev, base, &res); if (err) return err; -- 2.53.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window 2026-10-24 15:41 ` [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window Chris Scott @ 2026-10-26 7:48 ` Lorenzo Bianconi 0 siblings, 0 replies; 6+ messages in thread From: Lorenzo Bianconi @ 2026-10-26 7:48 UTC (permalink / raw) To: Chris Scott Cc: netdev, andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno, devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, pawlik.dan, zhengping.zhang [-- Attachment #1: Type: text/plain, Size: 4109 bytes --] > The EN7581 NPU can only address host DRAM at 0x80000000-0xbfffffff; > higher addresses alias the lower 1 GiB. The coherent buffers allocated > on the NPU device are all shared with the NPU: since mt76 uses the NPU > device as dma_dev, these are the NPU TX/RX descriptor rings, the HW-RRO > ba_bitmap/addr_elem/msdu_pg/session buffers and the NPU TXD buffers. > On a 2 GiB board nothing keeps them below 0xc0000000; they normally > land there only because of early-boot allocation order. With low DRAM > reserved away on W1700K the SoC hangs right after mt7996 firmware load. > > If the NPU node has an optional "dma" reserved-memory region, attach it > as the device coherent pool so all of these come from the window. The > next patch moves the mailbox buffers to coherent memory as well. > > Unlike a restricted-dma-pool this leaves streaming mappings alone. > Packet buffers are passed through to the WiFi DMA engine: on W1700K > with 96% of TX skbs and ~20% of RX page_pool buffers above 0xc0000000, > host-path traffic and sha256 file round-trips stay intact, at the same > throughput as without a pool, whereas a restricted-dma-pool (swiotlb > bouncing) costs ~22% of host-path TX. > > A device coherent pool has no fallback once full; mt76 and the mailbox > use ~10.7 MiB with MT7996, so the DT region should be 16 MiB. > > This patch was written with the help of Claude (Anthropic, claude- > opus-5-5). > > Link: https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com > Tested-by: Daniel Pawlik <pawlik.dan@gmail.com> > Signed-off-by: Chris Scott <gilroyscott1970@gmail.com> > --- > drivers/net/ethernet/airoha/airoha_npu.c | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c > index 4d3195eb00..069fd60680 100644 > --- a/drivers/net/ethernet/airoha/airoha_npu.c > +++ b/drivers/net/ethernet/airoha/airoha_npu.c > @@ -693,6 +693,11 @@ static const struct regmap_config regmap_config = { > .disable_locking = true, > }; > > +static void airoha_npu_rmem_release(void *data) > +{ > + of_reserved_mem_device_release(data); > +} > + > static int airoha_npu_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > @@ -776,6 +781,19 @@ static int airoha_npu_probe(struct platform_device *pdev) > if (err) > return err; > > + if (of_property_match_string(dev->of_node, "memory-region-names", > + "dma") >= 0) { > + err = of_reserved_mem_device_init_by_name(dev, dev->of_node, > + "dma"); > + if (err) > + return err; > + > + err = devm_add_action_or_reset(dev, airoha_npu_rmem_release, > + dev); > + if (err) > + return err; > + } nit: what about creating a dedicated routine for both firmware and dma memory regions. Something like: diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index 4d3195eb00f7..9c9c754f82c7 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -693,6 +693,23 @@ static const struct regmap_config regmap_config = { .disable_locking = true, }; +static int airoha_npu_reserve_mem_region(struct device *dev, + struct resource *res) +{ + int err; + + err = of_reserved_mem_region_to_resource(dev->of_node, 0, res); + if (err) + return err; + + if (of_property_match_string(dev->of_node, "memory-region-names", + "dma" >= 0)) { + ... + } + + return 0; +} + static int airoha_npu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -729,7 +746,7 @@ static int airoha_npu_probe(struct platform_device *pdev) if (IS_ERR(npu->regmap)) return PTR_ERR(npu->regmap); - err = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + err = airoha_npu_reserve_mem_region(dev, &res); if (err) return err; Regards, Lorenzo > + > err = airoha_npu_run_firmware(dev, base, &res); > if (err) > return err; > -- > 2.53.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages 2026-10-24 15:41 [RFC net-next 0/3] net: airoha: npu: keep NPU-shared DMA buffers in the NPU window Chris Scott 2026-10-24 15:41 ` [RFC net-next 1/3] dt-bindings: net: airoha: npu: add DMA pool memory region Chris Scott 2026-10-24 15:41 ` [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window Chris Scott @ 2026-10-24 15:41 ` Chris Scott 2026-10-26 7:50 ` Lorenzo Bianconi 2 siblings, 1 reply; 6+ messages in thread From: Chris Scott @ 2026-10-24 15:41 UTC (permalink / raw) To: netdev Cc: lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno, devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, pawlik.dan, zhengping.zhang, Chris Scott From: Daniel Pawlik <pawlik.dan@gmail.com> airoha_npu_send_msg() maps the caller's kzalloc() buffer with DMA_BIDIRECTIONAL. These buffers are small and not cacheline aligned, so on arm64 the mapping bounces through swiotlb. On a 2 GiB EN7581 board the default swiotlb pool sits above 0xc0000000 (0xff6cf000 on W1700K), outside the 0x80000000-0xbfffffff window the NPU can address; higher addresses alias the lower 1 GiB. On W1700K + MT7996 this makes WLAN_FUNC_GET_WAIT_NPU_VERSION read back 0.0 and mt76 does not bind NPU offload. Allocate one coherent buffer per NPU core at probe and reuse it under the per-core mailbox lock. With the previous patch it comes from the NPU DMA pool, inside the window. airoha_npu_send_msg() is also called from PPE foe_commit under spin_lock_bh(), which rules out a per-message GFP_ATOMIC coherent allocation. Add __airoha_npu_send_msg() with an optional reply buffer so GET callers copy only the trailing response payload; airoha_npu_send_msg() keeps copying the whole buffer back, like the bidirectional mapping. The original version of this patch was written with Cursor (composer-2); it was rebased onto net-next and its commit message rewritten with Claude (Anthropic). Link: https://lore.kernel.org/r/20260809152813.585797-1-pawlik.dan@gmail.com Link: https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com Signed-off-by: Daniel Pawlik <pawlik.dan@gmail.com> Signed-off-by: Chris Scott <gilroyscott1970@gmail.com> --- drivers/net/ethernet/airoha/airoha_npu.c | 65 +++++++++++++++++------ include/linux/soc/airoha/airoha_offload.h | 3 ++ 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index 069fd60680..3d1aa63dd5 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -24,6 +24,12 @@ #define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000 #define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE 0x10000 #define NPU_DUMP_SIZE 512 +/* + * Mailbox DMA payload size. Covers sizeof(struct ppe_mbox_data) (28) and + * WLAN TLV messages (header + payload); largest in-tree WLAN payload today + * is 16 bytes (INODE_TXRX_REG_ADDR). Keep headroom for future commands. + */ +#define AIROHA_NPU_MBOX_SIZE 256 #define REG_NPU_LOCAL_SRAM 0x0 @@ -161,23 +167,32 @@ struct wlan_mbox_data { DECLARE_FLEX_ARRAY(u8, d); }; -static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, - void *p, int size) +static int __airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + const void *data, int len, void *reply, + u16 reply_len) { - u16 core = 0; /* FIXME */ - u32 val, offset = core << 4; - dma_addr_t dma_addr; + struct airoha_npu_core *core = &npu->cores[0]; /* FIXME: core */ + u32 val, offset = 0; int ret; - dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL); - ret = dma_mapping_error(npu->dev, dma_addr); - if (ret) - return ret; + if (len > AIROHA_NPU_MBOX_SIZE) + return -EINVAL; + + if (reply && reply_len > len) + return -EINVAL; + + /* + * The NPU only reaches DRAM at 0x80000000-0xbfffffff; a streaming + * mapping of the caller buffer may bounce through swiotlb outside + * that window. Use the probe-time coherent buffer, which comes from + * the NPU DMA pool when one is declared. + */ + spin_lock_bh(&core->lock); - spin_lock_bh(&npu->cores[core].lock); + memcpy(core->buf, data, len); - regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, dma_addr); - regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, size); + regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, core->addr); + regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, len); regmap_read(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, &val); regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, val + 1); val = FIELD_PREP(MBOX_MSG_FUNC_ID, func_id) | MBOX_MSG_WAIT_RSP; @@ -190,13 +205,21 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, if (!ret && FIELD_GET(MBOX_MSG_STATUS, val) != NPU_MBOX_SUCCESS) ret = -EINVAL; - spin_unlock_bh(&npu->cores[core].lock); + /* Copy the trailing reply_len bytes of the response. */ + if (!ret && reply) + memcpy(reply, core->buf + len - reply_len, reply_len); - dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL); + spin_unlock_bh(&core->lock); return ret; } +static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + void *data, int len) +{ + return __airoha_npu_send_msg(npu, func_id, data, len, data, len); +} + static int airoha_npu_load_firmware(struct device *dev, void __iomem *addr, const char *fw_name, int fw_max_size) { @@ -500,9 +523,8 @@ static int airoha_npu_wlan_msg_get(struct airoha_npu *npu, int ifindex, wlan_data->func_type = NPU_OP_GET; wlan_data->func_id = func_id; - err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); - if (!err) - memcpy(data, wlan_data->d, data_len); + err = __airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len, + data, data_len); kfree(wlan_data); return err; @@ -794,6 +816,15 @@ static int airoha_npu_probe(struct platform_device *pdev) return err; } + for (i = 0; i < ARRAY_SIZE(npu->cores); i++) { + struct airoha_npu_core *core = &npu->cores[i]; + + core->buf = dmam_alloc_coherent(dev, AIROHA_NPU_MBOX_SIZE, + &core->addr, GFP_KERNEL); + if (!core->buf) + return -ENOMEM; + } + err = airoha_npu_run_firmware(dev, base, &res); if (err) return err; diff --git a/include/linux/soc/airoha/airoha_offload.h b/include/linux/soc/airoha/airoha_offload.h index 7589fccfee..16a988ad74 100644 --- a/include/linux/soc/airoha/airoha_offload.h +++ b/include/linux/soc/airoha/airoha_offload.h @@ -173,6 +173,9 @@ struct airoha_npu { /* protect concurrent npu memory accesses */ spinlock_t lock; struct work_struct wdt_work; + /* Coherent bounce buffer for mailbox cmd/rsp */ + void *buf; + dma_addr_t addr; } cores[NPU_NUM_CORES]; int irqs[NPU_NUM_IRQ]; -- 2.53.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages 2026-10-24 15:41 ` [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages Chris Scott @ 2026-10-26 7:50 ` Lorenzo Bianconi 0 siblings, 0 replies; 6+ messages in thread From: Lorenzo Bianconi @ 2026-10-26 7:50 UTC (permalink / raw) To: Chris Scott Cc: netdev, andrew+netdev, davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno, devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, pawlik.dan, zhengping.zhang [-- Attachment #1: Type: text/plain, Size: 6773 bytes --] > From: Daniel Pawlik <pawlik.dan@gmail.com> > > airoha_npu_send_msg() maps the caller's kzalloc() buffer with > DMA_BIDIRECTIONAL. These buffers are small and not cacheline aligned, > so on arm64 the mapping bounces through swiotlb. On a 2 GiB EN7581 > board the default swiotlb pool sits above 0xc0000000 (0xff6cf000 on > W1700K), outside the 0x80000000-0xbfffffff window the NPU can address; > higher addresses alias the lower 1 GiB. On W1700K + MT7996 this makes > WLAN_FUNC_GET_WAIT_NPU_VERSION read back 0.0 and mt76 does not bind > NPU offload. > > Allocate one coherent buffer per NPU core at probe and reuse it under > the per-core mailbox lock. With the previous patch it comes from the > NPU DMA pool, inside the window. airoha_npu_send_msg() is also called > from PPE foe_commit under spin_lock_bh(), which rules out a per-message > GFP_ATOMIC coherent allocation. > > Add __airoha_npu_send_msg() with an optional reply buffer so GET > callers copy only the trailing response payload; airoha_npu_send_msg() > keeps copying the whole buffer back, like the bidirectional mapping. > > The original version of this patch was written with Cursor (composer-2); > it was rebased onto net-next and its commit message rewritten with > Claude (Anthropic). > > Link: https://lore.kernel.org/r/20260809152813.585797-1-pawlik.dan@gmail.com > Link: https://lore.kernel.org/r/atCRsquzA1UxSpCc@mediatek.com > Signed-off-by: Daniel Pawlik <pawlik.dan@gmail.com> > Signed-off-by: Chris Scott <gilroyscott1970@gmail.com> > --- > drivers/net/ethernet/airoha/airoha_npu.c | 65 +++++++++++++++++------ > include/linux/soc/airoha/airoha_offload.h | 3 ++ > 2 files changed, 51 insertions(+), 17 deletions(-) > > diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c > index 069fd60680..3d1aa63dd5 100644 > --- a/drivers/net/ethernet/airoha/airoha_npu.c > +++ b/drivers/net/ethernet/airoha/airoha_npu.c > @@ -24,6 +24,12 @@ > #define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000 > #define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE 0x10000 > #define NPU_DUMP_SIZE 512 > +/* > + * Mailbox DMA payload size. Covers sizeof(struct ppe_mbox_data) (28) and > + * WLAN TLV messages (header + payload); largest in-tree WLAN payload today > + * is 16 bytes (INODE_TXRX_REG_ADDR). Keep headroom for future commands. > + */ > +#define AIROHA_NPU_MBOX_SIZE 256 > > #define REG_NPU_LOCAL_SRAM 0x0 > > @@ -161,23 +167,32 @@ struct wlan_mbox_data { > DECLARE_FLEX_ARRAY(u8, d); > }; > > -static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, > - void *p, int size) > +static int __airoha_npu_send_msg(struct airoha_npu *npu, int func_id, > + const void *data, int len, void *reply, > + u16 reply_len) > { > - u16 core = 0; /* FIXME */ > - u32 val, offset = core << 4; > - dma_addr_t dma_addr; > + struct airoha_npu_core *core = &npu->cores[0]; /* FIXME: core */ > + u32 val, offset = 0; > int ret; > > - dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL); > - ret = dma_mapping_error(npu->dev, dma_addr); > - if (ret) > - return ret; > + if (len > AIROHA_NPU_MBOX_SIZE) > + return -EINVAL; > + > + if (reply && reply_len > len) > + return -EINVAL; > + > + /* > + * The NPU only reaches DRAM at 0x80000000-0xbfffffff; a streaming > + * mapping of the caller buffer may bounce through swiotlb outside > + * that window. Use the probe-time coherent buffer, which comes from > + * the NPU DMA pool when one is declared. > + */ > + spin_lock_bh(&core->lock); > > - spin_lock_bh(&npu->cores[core].lock); > + memcpy(core->buf, data, len); > > - regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, dma_addr); > - regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, size); > + regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, core->addr); > + regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, len); > regmap_read(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, &val); > regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, val + 1); > val = FIELD_PREP(MBOX_MSG_FUNC_ID, func_id) | MBOX_MSG_WAIT_RSP; > @@ -190,13 +205,21 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, > if (!ret && FIELD_GET(MBOX_MSG_STATUS, val) != NPU_MBOX_SUCCESS) > ret = -EINVAL; > > - spin_unlock_bh(&npu->cores[core].lock); > + /* Copy the trailing reply_len bytes of the response. */ > + if (!ret && reply) > + memcpy(reply, core->buf + len - reply_len, reply_len); > > - dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL); > + spin_unlock_bh(&core->lock); > > return ret; > } > > +static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, > + void *data, int len) > +{ > + return __airoha_npu_send_msg(npu, func_id, data, len, data, len); IIUC airoha_npu_send_msg() is used when we do not expect any reply, correct? In this case we should have: return __airoha_npu_send_msg(npu, func_id, data, len, NULL, len); Am I missing something? Regards, Lorenzo > +} > + > static int airoha_npu_load_firmware(struct device *dev, void __iomem *addr, > const char *fw_name, int fw_max_size) > { > @@ -500,9 +523,8 @@ static int airoha_npu_wlan_msg_get(struct airoha_npu *npu, int ifindex, > wlan_data->func_type = NPU_OP_GET; > wlan_data->func_id = func_id; > > - err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); > - if (!err) > - memcpy(data, wlan_data->d, data_len); > + err = __airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len, > + data, data_len); > kfree(wlan_data); > > return err; > @@ -794,6 +816,15 @@ static int airoha_npu_probe(struct platform_device *pdev) > return err; > } > > + for (i = 0; i < ARRAY_SIZE(npu->cores); i++) { > + struct airoha_npu_core *core = &npu->cores[i]; > + > + core->buf = dmam_alloc_coherent(dev, AIROHA_NPU_MBOX_SIZE, > + &core->addr, GFP_KERNEL); > + if (!core->buf) > + return -ENOMEM; > + } > + > err = airoha_npu_run_firmware(dev, base, &res); > if (err) > return err; > diff --git a/include/linux/soc/airoha/airoha_offload.h b/include/linux/soc/airoha/airoha_offload.h > index 7589fccfee..16a988ad74 100644 > --- a/include/linux/soc/airoha/airoha_offload.h > +++ b/include/linux/soc/airoha/airoha_offload.h > @@ -173,6 +173,9 @@ struct airoha_npu { > /* protect concurrent npu memory accesses */ > spinlock_t lock; > struct work_struct wdt_work; > + /* Coherent bounce buffer for mailbox cmd/rsp */ > + void *buf; > + dma_addr_t addr; > } cores[NPU_NUM_CORES]; > > int irqs[NPU_NUM_IRQ]; > -- > 2.53.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-26 7:50 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-24 15:41 [RFC net-next 0/3] net: airoha: npu: keep NPU-shared DMA buffers in the NPU window Chris Scott 2026-10-24 15:41 ` [RFC net-next 1/3] dt-bindings: net: airoha: npu: add DMA pool memory region Chris Scott 2026-10-24 15:41 ` [RFC net-next 2/3] net: airoha: npu: attach a coherent pool in the NPU window Chris Scott 2026-10-26 7:48 ` Lorenzo Bianconi 2026-10-24 15:41 ` [RFC net-next 3/3] net: airoha: npu: use coherent memory for mailbox messages Chris Scott 2026-10-26 7:50 ` Lorenzo Bianconi
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®