* [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block
@ 2026-07-14 5:32 Vishnu Santhosh
2026-07-14 5:32 ` [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible Vishnu Santhosh
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Vishnu Santhosh @ 2026-07-14 5:32 UTC (permalink / raw)
To: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg
Cc: linux-arm-msm, netdev, devicetree, linux-kernel, Vishnu Santhosh,
chris.lew, Deepak Kumar Singh
On platforms where the modem DMAs into the BAM-DMUX RX data buffers and
the XPU (eXternal Protection Unit) enforces per-region access control,
each individually DMA-mapped RX buffer consumes an XPU resource group.
With only ~16 groups available on Shikra (mDSP, VMID 43 / NAV), the
per-buffer mappings exhaust the table and inbound transfers fault.
This series adds a qcom,shikra-bam-dmux compatible and have the driver
select QCOM_SCM_VMID_NAV internally via that compatible's match data.
When matched, the driver allocates all RX buffers as a single
contiguous coherent block and SCM-assigns it to HLOS plus the VMID
once at probe, consuming one XPU resource group instead of many.
Platforms that do not use the qcom,shikra-bam-dmux compatible are
unaffected: the existing per-buffer dma_map_single() path is
unchanged.
Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com>
---
Vishnu Santhosh (2):
dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible
net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block
.../devicetree/bindings/net/qcom,bam-dmux.yaml | 8 +-
drivers/net/wwan/Kconfig | 1 +
drivers/net/wwan/qcom_bam_dmux.c | 134 +++++++++++++++++++--
3 files changed, 132 insertions(+), 11 deletions(-)
---
base-commit: 3b029c035b34bbc693405ddf759f0e9b920c27f1
change-id: 20260714-qcom-bam-dmux-vmid-ext-d9289db310c1
Best regards,
--
Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible 2026-07-14 5:32 [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh @ 2026-07-14 5:32 ` Vishnu Santhosh 2026-07-14 7:11 ` Stephan Gerhold 2026-07-14 5:32 ` [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 7:53 ` [PATCH 0/2] " Jagielski, Jedrzej 2 siblings, 1 reply; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 5:32 UTC (permalink / raw) To: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm, netdev, devicetree, linux-kernel, Vishnu Santhosh, chris.lew, Deepak Kumar Singh On platforms where the modem DMAs into the BAM-DMUX RX data buffers and the XPU enforces per-region access control, each individually DMA-mapped RX buffer consumes an XPU resource group. With only ~16 groups available, the per-buffer mappings exhaust the table and inbound transfers fault. Add qcom,shikra-bam-dmux as an additional compatible for the Shikra SoC, paired with the generic qcom,bam-dmux fallback, so the driver can match on it via its of_device_id table. Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> --- Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml index 33746c238513d72366bc52359fb10f275475b331..27f0fdf285c17d6bfdecd5e59cad09912a5e821b 100644 --- a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml +++ b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml @@ -22,7 +22,13 @@ description: | properties: compatible: - const: qcom,bam-dmux + oneOf: + - const: qcom,bam-dmux + - items: + - enum: + # Shikra + - qcom,shikra-bam-dmux + - const: qcom,bam-dmux interrupts: description: -- 2.34.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible 2026-07-14 5:32 ` [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible Vishnu Santhosh @ 2026-07-14 7:11 ` Stephan Gerhold 2026-07-14 14:03 ` Vishnu Santhosh 0 siblings, 1 reply; 11+ messages in thread From: Stephan Gerhold @ 2026-07-14 7:11 UTC (permalink / raw) To: Vishnu Santhosh Cc: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg, linux-arm-msm, netdev, devicetree, linux-kernel, chris.lew, Deepak Kumar Singh On Tue, Jul 14, 2026 at 11:02:31AM +0530, Vishnu Santhosh wrote: > On platforms where the modem DMAs into the BAM-DMUX RX data buffers and > the XPU enforces per-region access control, each individually > DMA-mapped RX buffer consumes an XPU resource group. With only ~16 > groups available, the per-buffer mappings exhaust the table and inbound > transfers fault. > > Add qcom,shikra-bam-dmux as an additional compatible for the Shikra SoC, > paired with the generic qcom,bam-dmux fallback, so the driver can match > on it via its of_device_id table. > > Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> > Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> > Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> IMHO (the DT maintainers might disagree) this is not a different BAM DMUX hardware block on Shikra, just a different firmware configuration. I'm sure the existing SoCs also have those XPU blocks, they just don't make use of it. Personally, I would rather describe this with an optional "qcom,vmid" property similar to your bam-dma patch, allowed for all SoCs. Thanks, Stephan ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible 2026-07-14 7:11 ` Stephan Gerhold @ 2026-07-14 14:03 ` Vishnu Santhosh 0 siblings, 0 replies; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 14:03 UTC (permalink / raw) To: Stephan Gerhold Cc: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg, linux-arm-msm, netdev, devicetree, linux-kernel, chris.lew, Deepak Kumar Singh, Konrad Dybcio On 14-07-2026 12:41 pm, Stephan Gerhold wrote: > On Tue, Jul 14, 2026 at 11:02:31AM +0530, Vishnu Santhosh wrote: >> On platforms where the modem DMAs into the BAM-DMUX RX data buffers and >> the XPU enforces per-region access control, each individually >> DMA-mapped RX buffer consumes an XPU resource group. With only ~16 >> groups available, the per-buffer mappings exhaust the table and inbound >> transfers fault. >> >> Add qcom,shikra-bam-dmux as an additional compatible for the Shikra SoC, >> paired with the generic qcom,bam-dmux fallback, so the driver can match >> on it via its of_device_id table. >> >> Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> > IMHO (the DT maintainers might disagree) this is not a different > BAM DMUX hardware block on Shikra, just a different firmware > configuration. I'm sure the existing SoCs also have those XPU blocks, > they just don't make use of it. > > Personally, I would rather describe this with an optional "qcom,vmid" > property similar to your bam-dma patch, allowed for all SoCs. > > Thanks, > Stephan Thanks Stephan. Adding Konrad (Cc), since this compatible-string / match-data approach was his suggestion on an earlier revision of this series send for internal review, specifically because BAM-DMUX is a singleton per SoC. Konrad, given Stephan's point, would you still prefer the compatible-string / match-data approach, or does the optional qcom,vmid property (matching the bam-dma series) make more sense here? Happy to go either way once you've both aligned. Thanks, Vishnu ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 5:32 [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 5:32 ` [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible Vishnu Santhosh @ 2026-07-14 5:32 ` Vishnu Santhosh 2026-07-14 7:35 ` Stephan Gerhold 2026-07-14 7:55 ` Jagielski, Jedrzej 2026-07-14 7:53 ` [PATCH 0/2] " Jagielski, Jedrzej 2 siblings, 2 replies; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 5:32 UTC (permalink / raw) To: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm, netdev, devicetree, linux-kernel, Vishnu Santhosh, chris.lew, Deepak Kumar Singh On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces per-region access control, each individually DMA-mapped RX buffer requires its own XPU resource group (RG). With ~16 RGs available, the 32 per-buffer dma_map_single() calls exhaust the table and the first inbound transfer faults with an XPU violation. BAM-DMUX is a singleton (exactly one instance per SoC), so the destination VMID does not need to be a DT property; it is looked up from the compatible string's match data instead. Add struct bam_dmux_data with a single vmid field, and a shikra_data instance hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as a single contiguous dma_alloc_coherent() block and SCM-assign that block to HLOS plus the VMID once at probe. This reduces RG consumption from 32 to 1. The block is never reclaimed across a modem power cycle (bam_dmux_power_off() does not touch it), so the probe-time assignment covers every subsequent restart without re-assigning or reclaiming. It is reclaimed to HLOS only once, at remove or on a probe error, and if that reclaim fails it is leaked rather than returned to the page allocator. Each rx_skbs[] slot is pre-assigned its virtual and DMA address from the block, so no per-buffer mapping is needed at power-on. Because the coherent block is not page-backed, received payload is copied into a regular netdev skb before handoff to the network stack; this is an unavoidable extra copy on the XPU-enforced RX path. Platforms without match data are unaffected: rx_virt stays NULL, no coherent memory is allocated, and the per-buffer dma_map_single() path is unchanged. Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> --- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/qcom_bam_dmux.c | 134 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 125 insertions(+), 10 deletions(-) diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 958dbc7347fa84ee869439bf8b503037faab8bef..1b133c56231615269698140187ca3141dfe48dbf 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -65,6 +65,7 @@ config MHI_WWAN_MBIM config QCOM_BAM_DMUX tristate "Qualcomm BAM-DMUX WWAN network driver" depends on (DMA_ENGINE && PM && QCOM_SMEM_STATE) || COMPILE_TEST + select QCOM_SCM help The BAM Data Multiplexer provides access to the network data channels of modems integrated into many older Qualcomm SoCs, e.g. Qualcomm diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c index cc6ace8d64371eb8d00c638a39b234ee540b83c9..247230b720e6011876d5c429badbb5a1f34fc576 100644 --- a/drivers/net/wwan/qcom_bam_dmux.c +++ b/drivers/net/wwan/qcom_bam_dmux.c @@ -9,10 +9,12 @@ #include <linux/completion.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> +#include <linux/firmware/qcom/qcom_scm.h> #include <linux/if_arp.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/soc/qcom/smem_state.h> @@ -62,6 +64,7 @@ struct bam_dmux_skb_dma { struct bam_dmux *dmux; struct sk_buff *skb; dma_addr_t addr; + void *rx_virt; /* non-NULL: slot in the coherent RX block */ }; struct bam_dmux { @@ -75,6 +78,10 @@ struct bam_dmux { struct completion pc_ack_completion; struct dma_chan *rx, *tx; + /* Single coherent block backing all RX buffers, NULL if unused */ + void *rx_buf; + dma_addr_t rx_buf_dma; + u64 rx_buf_perms; /* SCM source-VMID bitmask of rx_buf */ struct bam_dmux_skb_dma rx_skbs[BAM_DMUX_NUM_SKB]; struct bam_dmux_skb_dma tx_skbs[BAM_DMUX_NUM_SKB]; spinlock_t tx_lock; /* Protect tx_skbs, tx_next_skb */ @@ -92,6 +99,10 @@ struct bam_dmux_netdev { u8 ch; }; +struct bam_dmux_data { + u32 vmid; +}; + static void bam_dmux_pc_vote(struct bam_dmux *dmux, bool enable) { reinit_completion(&dmux->pc_ack_completion); @@ -111,6 +122,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, { struct device *dev = skb_dma->dmux->dev; + if (skb_dma->rx_virt) /* coherent RX slot: addr pre-assigned */ + return true; + skb_dma->addr = dma_map_single(dev, skb_dma->skb->data, skb_dma->skb->len, dir); if (dma_mapping_error(dev, skb_dma->addr)) { dev_err(dev, "Failed to DMA map buffer\n"); @@ -124,6 +138,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, static void bam_dmux_skb_dma_unmap(struct bam_dmux_skb_dma *skb_dma, enum dma_data_direction dir) { + if (skb_dma->rx_virt) /* coherent RX slot: nothing to unmap */ + return; + dma_unmap_single(skb_dma->dmux->dev, skb_dma->addr, skb_dma->skb->len, dir); skb_dma->addr = 0; } @@ -468,9 +485,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) { struct bam_dmux *dmux = skb_dma->dmux; struct dma_async_tx_descriptor *desc; + size_t len = skb_dma->rx_virt ? BAM_DMUX_BUFFER_SIZE : skb_dma->skb->len; desc = dmaengine_prep_slave_single(dmux->rx, skb_dma->addr, - skb_dma->skb->len, DMA_DEV_TO_MEM, + len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!desc) { dev_err(dmux->dev, "Failed to prepare RX DMA buffer\n"); @@ -485,6 +503,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp) { + /* Coherent RX slots have rx_virt and addr pre-assigned at probe. */ + if (skb_dma->rx_virt) + return bam_dmux_skb_dma_submit_rx(skb_dma); + if (!skb_dma->skb) { skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp); if (!skb_dma->skb) @@ -499,9 +521,10 @@ static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gf static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) { struct bam_dmux *dmux = skb_dma->dmux; - struct sk_buff *skb = skb_dma->skb; - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; + struct bam_dmux_hdr *hdr = skb_dma->rx_virt ? skb_dma->rx_virt : + (struct bam_dmux_hdr *)skb_dma->skb->data; struct net_device *netdev = dmux->netdevs[hdr->ch]; + struct sk_buff *skb; if (!netdev || !netif_running(netdev)) { dev_warn(dmux->dev, "Data for inactive channel %u\n", hdr->ch); @@ -514,10 +537,18 @@ static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) return; } - skb_dma->skb = NULL; /* Hand over to network stack */ - - skb_pull(skb, sizeof(*hdr)); - skb_trim(skb, hdr->len); + if (skb_dma->rx_virt) { + /* Coherent block is not page-backed: copy out to a real skb */ + skb = netdev_alloc_skb(netdev, hdr->len); + if (!skb) + return; + skb_put_data(skb, (u8 *)skb_dma->rx_virt + sizeof(*hdr), hdr->len); + } else { + skb = skb_dma->skb; + skb_dma->skb = NULL; /* Hand over to network stack */ + skb_pull(skb, sizeof(*hdr)); + skb_trim(skb, hdr->len); + } skb->dev = netdev; /* Only Raw-IP/QMAP is supported by this driver */ @@ -574,10 +605,14 @@ static void bam_dmux_rx_callback(void *data) { struct bam_dmux_skb_dma *skb_dma = data; struct bam_dmux *dmux = skb_dma->dmux; - struct sk_buff *skb = skb_dma->skb; - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; + struct bam_dmux_hdr *hdr; - bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); + if (skb_dma->rx_virt) { + hdr = skb_dma->rx_virt; /* coherent RX: no skb to unmap */ + } else { + bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); + hdr = (struct bam_dmux_hdr *)skb_dma->skb->data; + } if (hdr->magic != BAM_DMUX_HDR_MAGIC) { dev_err(dmux->dev, "Invalid magic in header: %#x\n", hdr->magic); @@ -644,6 +679,9 @@ static void bam_dmux_free_skbs(struct bam_dmux_skb_dma skbs[], for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { struct bam_dmux_skb_dma *skb_dma = &skbs[i]; + if (skb_dma->rx_virt) /* coherent block freed at remove */ + continue; + if (skb_dma->addr) bam_dmux_skb_dma_unmap(skb_dma, dir); if (skb_dma->skb) { @@ -762,6 +800,71 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) return 0; } +static int bam_dmux_alloc_coherent_rx(struct bam_dmux *dmux) +{ + struct device *dev = dmux->dev; + const struct bam_dmux_data *data = of_device_get_match_data(dev); + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; + u64 src = BIT_ULL(QCOM_SCM_VMID_HLOS); + struct qcom_scm_vmperm dst[2]; + int i, ret; + + if (!data) + return 0; + + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + + dst[0].vmid = QCOM_SCM_VMID_HLOS; + dst[0].perm = QCOM_SCM_PERM_RW; + dst[1].vmid = data->vmid; + dst[1].perm = QCOM_SCM_PERM_RW; + + dmux->rx_buf = dma_alloc_coherent(dev, size, &dmux->rx_buf_dma, GFP_KERNEL); + if (!dmux->rx_buf) + return -ENOMEM; + + for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { + dmux->rx_skbs[i].rx_virt = dmux->rx_buf + i * BAM_DMUX_BUFFER_SIZE; + dmux->rx_skbs[i].addr = dmux->rx_buf_dma + i * BAM_DMUX_BUFFER_SIZE; + } + + ret = qcom_scm_assign_mem(dmux->rx_buf_dma, size, &src, dst, ARRAY_SIZE(dst)); + if (ret) { + dev_err(dev, "SCM assign RX block failed: %d\n", ret); + dma_free_coherent(dev, size, dmux->rx_buf, dmux->rx_buf_dma); + dmux->rx_buf = NULL; + return ret; + } + dmux->rx_buf_perms = src; + + return 0; +} + +static void bam_dmux_free_coherent_rx(struct bam_dmux *dmux) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; + + if (!dmux->rx_buf) + return; + + if (dmux->rx_buf_perms) { + if (qcom_scm_assign_mem(dmux->rx_buf_dma, size, &dmux->rx_buf_perms, + &hlos, 1)) { + dev_err(dmux->dev, "SCM reclaim RX block failed; leaking\n"); + return; + } + dmux->rx_buf_perms = 0; + } + + dma_free_coherent(dmux->dev, size, dmux->rx_buf, dmux->rx_buf_dma); + dmux->rx_buf = NULL; +} + static int bam_dmux_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -809,6 +912,10 @@ static int bam_dmux_probe(struct platform_device *pdev) dmux->tx_skbs[i].dmux = dmux; } + ret = bam_dmux_alloc_coherent_rx(dmux); + if (ret) + return ret; + /* Runtime PM manages our own power vote. * Note that the RX path may be active even if we are runtime suspended, * since it is controlled by the remote side. @@ -845,6 +952,7 @@ static int bam_dmux_probe(struct platform_device *pdev) err_disable_pm: pm_runtime_disable(dev); pm_runtime_dont_use_autosuspend(dev); + bam_dmux_free_coherent_rx(dmux); return ret; } @@ -879,13 +987,19 @@ static void bam_dmux_remove(struct platform_device *pdev) disable_irq(dmux->pc_irq); bam_dmux_power_off(dmux); bam_dmux_free_skbs(dmux->tx_skbs, DMA_TO_DEVICE); + bam_dmux_free_coherent_rx(dmux); } static const struct dev_pm_ops bam_dmux_pm_ops = { SET_RUNTIME_PM_OPS(bam_dmux_runtime_suspend, bam_dmux_runtime_resume, NULL) }; +static const struct bam_dmux_data shikra_data = { + .vmid = QCOM_SCM_VMID_NAV, +}; + static const struct of_device_id bam_dmux_of_match[] = { + { .compatible = "qcom,shikra-bam-dmux", .data = &shikra_data }, { .compatible = "qcom,bam-dmux" }, { /* sentinel */ } }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 5:32 ` [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh @ 2026-07-14 7:35 ` Stephan Gerhold 2026-07-14 15:47 ` Vishnu Santhosh 2026-07-14 7:55 ` Jagielski, Jedrzej 1 sibling, 1 reply; 11+ messages in thread From: Stephan Gerhold @ 2026-07-14 7:35 UTC (permalink / raw) To: Vishnu Santhosh Cc: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg, linux-arm-msm, netdev, devicetree, linux-kernel, chris.lew, Deepak Kumar Singh On Tue, Jul 14, 2026 at 11:02:32AM +0530, Vishnu Santhosh wrote: > On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / > NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces > per-region access control, each individually DMA-mapped RX buffer > requires its own XPU resource group (RG). With ~16 RGs available, the > 32 per-buffer dma_map_single() calls exhaust the table and the first > inbound transfer faults with an XPU violation. > > BAM-DMUX is a singleton (exactly one instance per SoC), so the > destination VMID does not need to be a DT property; it is looked up > from the compatible string's match data instead. Add struct > bam_dmux_data with a single vmid field, and a shikra_data instance > hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. > > When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as > a single contiguous dma_alloc_coherent() block and SCM-assign that > block to HLOS plus the VMID once at probe. This reduces RG consumption > from 32 to 1. The block is never reclaimed across a modem power cycle > (bam_dmux_power_off() does not touch it), so the probe-time assignment > covers every subsequent restart without re-assigning or reclaiming. It > is reclaimed to HLOS only once, at remove or on a probe error, and if > that reclaim fails it is leaked rather than returned to the page > allocator. > > Each rx_skbs[] slot is pre-assigned its virtual and DMA address from > the block, so no per-buffer mapping is needed at power-on. Because the > coherent block is not page-backed, received payload is copied into a > regular netdev skb before handoff to the network stack; this is an > unavoidable extra copy on the XPU-enforced RX path. > > Platforms without match data are unaffected: rx_virt stays NULL, no > coherent memory is allocated, and the per-buffer dma_map_single() path > is unchanged. > > Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> > Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> > Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> So how do you handle TX buffers? Right now, they are just passed on from the net subsystem. There can be up to 32 TX buffers in progress as well. Overall, I have mixed feelings about this patch. It looks reasonably simple, but fundamentally I don't understand why we need to go back to the old days of implementing protection using a highly limited MPU (in your case: the xPU). Why does the setup of BAM-DMUX differ e.g. from the setup for the crypto engine? Crypto is also using bam-dma, but it avoids this inflexibility by making use of the &apps_smmu. Is BAM-DMUX not covered by the SMMU? Or did you just decide to bypass the SMMU in this case? (If so: Why?) If you had BAM-DMUX mapped using the SMMU you would get all of this for free. No changes would be needed in the BAM-DMUX driver ... Thanks, Stephan ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 7:35 ` Stephan Gerhold @ 2026-07-14 15:47 ` Vishnu Santhosh 0 siblings, 0 replies; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 15:47 UTC (permalink / raw) To: Stephan Gerhold Cc: Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg, linux-arm-msm, netdev, devicetree, linux-kernel, chris.lew, Deepak Kumar Singh On 14-07-2026 01:05 pm, Stephan Gerhold wrote: > On Tue, Jul 14, 2026 at 11:02:32AM +0530, Vishnu Santhosh wrote: >> On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / >> NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces >> per-region access control, each individually DMA-mapped RX buffer >> requires its own XPU resource group (RG). With ~16 RGs available, the >> 32 per-buffer dma_map_single() calls exhaust the table and the first >> inbound transfer faults with an XPU violation. >> >> BAM-DMUX is a singleton (exactly one instance per SoC), so the >> destination VMID does not need to be a DT property; it is looked up >> from the compatible string's match data instead. Add struct >> bam_dmux_data with a single vmid field, and a shikra_data instance >> hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. >> >> When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as >> a single contiguous dma_alloc_coherent() block and SCM-assign that >> block to HLOS plus the VMID once at probe. This reduces RG consumption >> from 32 to 1. The block is never reclaimed across a modem power cycle >> (bam_dmux_power_off() does not touch it), so the probe-time assignment >> covers every subsequent restart without re-assigning or reclaiming. It >> is reclaimed to HLOS only once, at remove or on a probe error, and if >> that reclaim fails it is leaked rather than returned to the page >> allocator. >> >> Each rx_skbs[] slot is pre-assigned its virtual and DMA address from >> the block, so no per-buffer mapping is needed at power-on. Because the >> coherent block is not page-backed, received payload is copied into a >> regular netdev skb before handoff to the network stack; this is an >> unavoidable extra copy on the XPU-enforced RX path. >> >> Platforms without match data are unaffected: rx_virt stays NULL, no >> coherent memory is allocated, and the per-buffer dma_map_single() path >> is unchanged. >> >> Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> > So how do you handle TX buffers? Right now, they are just passed on from > the net subsystem. There can be up to 32 TX buffers in progress as well. > > Overall, I have mixed feelings about this patch. It looks reasonably > simple, but fundamentally I don't understand why we need to go back to > the old days of implementing protection using a highly limited MPU (in > your case: the xPU). > > Why does the setup of BAM-DMUX differ e.g. from the setup for the crypto > engine? Crypto is also using bam-dma, but it avoids this inflexibility > by making use of the &apps_smmu. Is BAM-DMUX not covered by the SMMU? Or > did you just decide to bypass the SMMU in this case? (If so: Why?) > > If you had BAM-DMUX mapped using the SMMU you would get all of this for > free. No changes would be needed in the BAM-DMUX driver ... > > Thanks, > Stephan Thanks for pointing out. We were seeing XPU violations on descriptor FIFO accesses in the RX path. This series resolves the RX-side faults, which is why we posted it. It appears that the TX path requires equivalent handling, and we'll include the necessary TX changes in v2 of this series. Currently, the SMMU does not cover this A2 BAM instance on Shikra, which is why we opted for the SCM-assign approach. I'll check with the hardware team to better understand why BAM-DMUX is not behind the SMMU, gather the relevant details, and get back. Thanks, Vishnu ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 5:32 ` [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 7:35 ` Stephan Gerhold @ 2026-07-14 7:55 ` Jagielski, Jedrzej 2026-07-14 16:31 ` Vishnu Santhosh 1 sibling, 1 reply; 11+ messages in thread From: Jagielski, Jedrzej @ 2026-07-14 7:55 UTC (permalink / raw) To: Vishnu Santhosh, Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, chris.lew@oss.qualcomm.com, Deepak Kumar Singh From: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> Sent: Tuesday, July 14, 2026 7:33 AM >On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / >NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces >per-region access control, each individually DMA-mapped RX buffer >requires its own XPU resource group (RG). With ~16 RGs available, the >32 per-buffer dma_map_single() calls exhaust the table and the first >inbound transfer faults with an XPU violation. > >BAM-DMUX is a singleton (exactly one instance per SoC), so the >destination VMID does not need to be a DT property; it is looked up >from the compatible string's match data instead. Add struct >bam_dmux_data with a single vmid field, and a shikra_data instance >hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. > >When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as >a single contiguous dma_alloc_coherent() block and SCM-assign that >block to HLOS plus the VMID once at probe. This reduces RG consumption >from 32 to 1. The block is never reclaimed across a modem power cycle >(bam_dmux_power_off() does not touch it), so the probe-time assignment >covers every subsequent restart without re-assigning or reclaiming. It >is reclaimed to HLOS only once, at remove or on a probe error, and if >that reclaim fails it is leaked rather than returned to the page >allocator. > >Each rx_skbs[] slot is pre-assigned its virtual and DMA address from >the block, so no per-buffer mapping is needed at power-on. Because the >coherent block is not page-backed, received payload is copied into a >regular netdev skb before handoff to the network stack; this is an >unavoidable extra copy on the XPU-enforced RX path. > >Platforms without match data are unaffected: rx_virt stays NULL, no >coherent memory is allocated, and the per-buffer dma_map_single() path >is unchanged. > >Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> >--- > drivers/net/wwan/Kconfig | 1 + > drivers/net/wwan/qcom_bam_dmux.c | 134 ++++++++++++++++++++++++++++++++++++--- > 2 files changed, 125 insertions(+), 10 deletions(-) > >diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig >index 958dbc7347fa84ee869439bf8b503037faab8bef..1b133c56231615269698140187ca3141dfe48dbf 100644 >--- a/drivers/net/wwan/Kconfig >+++ b/drivers/net/wwan/Kconfig >@@ -65,6 +65,7 @@ config MHI_WWAN_MBIM > config QCOM_BAM_DMUX > tristate "Qualcomm BAM-DMUX WWAN network driver" > depends on (DMA_ENGINE && PM && QCOM_SMEM_STATE) || COMPILE_TEST >+ select QCOM_SCM > help > The BAM Data Multiplexer provides access to the network data channels > of modems integrated into many older Qualcomm SoCs, e.g. Qualcomm >diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c >index cc6ace8d64371eb8d00c638a39b234ee540b83c9..247230b720e6011876d5c429badbb5a1f34fc576 100644 >--- a/drivers/net/wwan/qcom_bam_dmux.c >+++ b/drivers/net/wwan/qcom_bam_dmux.c >@@ -9,10 +9,12 @@ > #include <linux/completion.h> > #include <linux/dma-mapping.h> > #include <linux/dmaengine.h> >+#include <linux/firmware/qcom/qcom_scm.h> > #include <linux/if_arp.h> > #include <linux/interrupt.h> > #include <linux/module.h> > #include <linux/netdevice.h> >+#include <linux/of.h> > #include <linux/platform_device.h> > #include <linux/pm_runtime.h> > #include <linux/soc/qcom/smem_state.h> >@@ -62,6 +64,7 @@ struct bam_dmux_skb_dma { > struct bam_dmux *dmux; > struct sk_buff *skb; > dma_addr_t addr; >+ void *rx_virt; /* non-NULL: slot in the coherent RX block */ > }; > > struct bam_dmux { >@@ -75,6 +78,10 @@ struct bam_dmux { > struct completion pc_ack_completion; > > struct dma_chan *rx, *tx; >+ /* Single coherent block backing all RX buffers, NULL if unused */ >+ void *rx_buf; >+ dma_addr_t rx_buf_dma; >+ u64 rx_buf_perms; /* SCM source-VMID bitmask of rx_buf */ > struct bam_dmux_skb_dma rx_skbs[BAM_DMUX_NUM_SKB]; > struct bam_dmux_skb_dma tx_skbs[BAM_DMUX_NUM_SKB]; > spinlock_t tx_lock; /* Protect tx_skbs, tx_next_skb */ >@@ -92,6 +99,10 @@ struct bam_dmux_netdev { > u8 ch; > }; > >+struct bam_dmux_data { >+ u32 vmid; >+}; >+ do we need to introduce dedicated struct just to cover u32? > static void bam_dmux_pc_vote(struct bam_dmux *dmux, bool enable) > { > reinit_completion(&dmux->pc_ack_completion); >@@ -111,6 +122,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, > { > struct device *dev = skb_dma->dmux->dev; > >+ if (skb_dma->rx_virt) /* coherent RX slot: addr pre-assigned */ >+ return true; >+ > skb_dma->addr = dma_map_single(dev, skb_dma->skb->data, skb_dma->skb->len, dir); > if (dma_mapping_error(dev, skb_dma->addr)) { > dev_err(dev, "Failed to DMA map buffer\n"); >@@ -124,6 +138,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, > static void bam_dmux_skb_dma_unmap(struct bam_dmux_skb_dma *skb_dma, > enum dma_data_direction dir) > { >+ if (skb_dma->rx_virt) /* coherent RX slot: nothing to unmap */ >+ return; >+ > dma_unmap_single(skb_dma->dmux->dev, skb_dma->addr, skb_dma->skb->len, dir); > skb_dma->addr = 0; > } >@@ -468,9 +485,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) > { > struct bam_dmux *dmux = skb_dma->dmux; > struct dma_async_tx_descriptor *desc; >+ size_t len = skb_dma->rx_virt ? BAM_DMUX_BUFFER_SIZE : skb_dma->skb->len; please stick to RCT please fix it here and for the following where RCT is violated > > desc = dmaengine_prep_slave_single(dmux->rx, skb_dma->addr, >- skb_dma->skb->len, DMA_DEV_TO_MEM, >+ len, DMA_DEV_TO_MEM, > DMA_PREP_INTERRUPT); > if (!desc) { > dev_err(dmux->dev, "Failed to prepare RX DMA buffer\n"); >@@ -485,6 +503,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) > > static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp) > { >+ /* Coherent RX slots have rx_virt and addr pre-assigned at probe. */ >+ if (skb_dma->rx_virt) >+ return bam_dmux_skb_dma_submit_rx(skb_dma); >+ > if (!skb_dma->skb) { > skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp); > if (!skb_dma->skb) >@@ -499,9 +521,10 @@ static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gf > static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) > { > struct bam_dmux *dmux = skb_dma->dmux; >- struct sk_buff *skb = skb_dma->skb; >- struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; >+ struct bam_dmux_hdr *hdr = skb_dma->rx_virt ? skb_dma->rx_virt : >+ (struct bam_dmux_hdr *)skb_dma->skb->data; > struct net_device *netdev = dmux->netdevs[hdr->ch]; >+ struct sk_buff *skb; > > if (!netdev || !netif_running(netdev)) { > dev_warn(dmux->dev, "Data for inactive channel %u\n", hdr->ch); >@@ -514,10 +537,18 @@ static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) > return; > } > >- skb_dma->skb = NULL; /* Hand over to network stack */ >- >- skb_pull(skb, sizeof(*hdr)); >- skb_trim(skb, hdr->len); >+ if (skb_dma->rx_virt) { >+ /* Coherent block is not page-backed: copy out to a real skb */ >+ skb = netdev_alloc_skb(netdev, hdr->len); >+ if (!skb) >+ return; >+ skb_put_data(skb, (u8 *)skb_dma->rx_virt + sizeof(*hdr), hdr->len); >+ } else { >+ skb = skb_dma->skb; >+ skb_dma->skb = NULL; /* Hand over to network stack */ >+ skb_pull(skb, sizeof(*hdr)); >+ skb_trim(skb, hdr->len); >+ } > skb->dev = netdev; > > /* Only Raw-IP/QMAP is supported by this driver */ >@@ -574,10 +605,14 @@ static void bam_dmux_rx_callback(void *data) > { > struct bam_dmux_skb_dma *skb_dma = data; > struct bam_dmux *dmux = skb_dma->dmux; >- struct sk_buff *skb = skb_dma->skb; >- struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; >+ struct bam_dmux_hdr *hdr; > >- bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); >+ if (skb_dma->rx_virt) { >+ hdr = skb_dma->rx_virt; /* coherent RX: no skb to unmap */ >+ } else { >+ bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); >+ hdr = (struct bam_dmux_hdr *)skb_dma->skb->data; >+ } > > if (hdr->magic != BAM_DMUX_HDR_MAGIC) { > dev_err(dmux->dev, "Invalid magic in header: %#x\n", hdr->magic); >@@ -644,6 +679,9 @@ static void bam_dmux_free_skbs(struct bam_dmux_skb_dma skbs[], > for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { > struct bam_dmux_skb_dma *skb_dma = &skbs[i]; > >+ if (skb_dma->rx_virt) /* coherent block freed at remove */ >+ continue; >+ > if (skb_dma->addr) > bam_dmux_skb_dma_unmap(skb_dma, dir); > if (skb_dma->skb) { >@@ -762,6 +800,71 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) > return 0; > } > >+static int bam_dmux_alloc_coherent_rx(struct bam_dmux *dmux) >+{ >+ struct device *dev = dmux->dev; >+ const struct bam_dmux_data *data = of_device_get_match_data(dev); >+ size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; >+ u64 src = BIT_ULL(QCOM_SCM_VMID_HLOS); >+ struct qcom_scm_vmperm dst[2]; >+ int i, ret; >+ >+ if (!data) >+ return 0; is there actually any chance to really trigger that check? or just theoretical case? >+ >+ if (!qcom_scm_is_available()) >+ return -EPROBE_DEFER; >+ >+ dst[0].vmid = QCOM_SCM_VMID_HLOS; >+ dst[0].perm = QCOM_SCM_PERM_RW; >+ dst[1].vmid = data->vmid; >+ dst[1].perm = QCOM_SCM_PERM_RW; >+ >+ dmux->rx_buf = dma_alloc_coherent(dev, size, &dmux->rx_buf_dma, GFP_KERNEL); >+ if (!dmux->rx_buf) >+ return -ENOMEM; >+ >+ for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { >+ dmux->rx_skbs[i].rx_virt = dmux->rx_buf + i * BAM_DMUX_BUFFER_SIZE; >+ dmux->rx_skbs[i].addr = dmux->rx_buf_dma + i * BAM_DMUX_BUFFER_SIZE; >+ } >+ >+ ret = qcom_scm_assign_mem(dmux->rx_buf_dma, size, &src, dst, ARRAY_SIZE(dst)); >+ if (ret) { >+ dev_err(dev, "SCM assign RX block failed: %d\n", ret); >+ dma_free_coherent(dev, size, dmux->rx_buf, dmux->rx_buf_dma); >+ dmux->rx_buf = NULL; >+ return ret; >+ } >+ dmux->rx_buf_perms = src; >+ >+ return 0; >+} >+ >+static void bam_dmux_free_coherent_rx(struct bam_dmux *dmux) >+{ >+ struct qcom_scm_vmperm hlos = { >+ .vmid = QCOM_SCM_VMID_HLOS, >+ .perm = QCOM_SCM_PERM_RW, >+ }; >+ size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; >+ >+ if (!dmux->rx_buf) >+ return; >+ >+ if (dmux->rx_buf_perms) { >+ if (qcom_scm_assign_mem(dmux->rx_buf_dma, size, &dmux->rx_buf_perms, >+ &hlos, 1)) { >+ dev_err(dmux->dev, "SCM reclaim RX block failed; leaking\n"); >+ return; >+ } >+ dmux->rx_buf_perms = 0; >+ } >+ >+ dma_free_coherent(dmux->dev, size, dmux->rx_buf, dmux->rx_buf_dma); >+ dmux->rx_buf = NULL; >+} >+ > static int bam_dmux_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; >@@ -809,6 +912,10 @@ static int bam_dmux_probe(struct platform_device *pdev) > dmux->tx_skbs[i].dmux = dmux; > } > >+ ret = bam_dmux_alloc_coherent_rx(dmux); >+ if (ret) >+ return ret; >+ > /* Runtime PM manages our own power vote. > * Note that the RX path may be active even if we are runtime suspended, > * since it is controlled by the remote side. >@@ -845,6 +952,7 @@ static int bam_dmux_probe(struct platform_device *pdev) > err_disable_pm: > pm_runtime_disable(dev); > pm_runtime_dont_use_autosuspend(dev); >+ bam_dmux_free_coherent_rx(dmux); > return ret; > } > >@@ -879,13 +987,19 @@ static void bam_dmux_remove(struct platform_device *pdev) > disable_irq(dmux->pc_irq); > bam_dmux_power_off(dmux); > bam_dmux_free_skbs(dmux->tx_skbs, DMA_TO_DEVICE); >+ bam_dmux_free_coherent_rx(dmux); > } > > static const struct dev_pm_ops bam_dmux_pm_ops = { > SET_RUNTIME_PM_OPS(bam_dmux_runtime_suspend, bam_dmux_runtime_resume, NULL) > }; > >+static const struct bam_dmux_data shikra_data = { >+ .vmid = QCOM_SCM_VMID_NAV, >+}; >+ > static const struct of_device_id bam_dmux_of_match[] = { >+ { .compatible = "qcom,shikra-bam-dmux", .data = &shikra_data }, > { .compatible = "qcom,bam-dmux" }, > { /* sentinel */ } > }; > >-- >2.34.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 7:55 ` Jagielski, Jedrzej @ 2026-07-14 16:31 ` Vishnu Santhosh 0 siblings, 0 replies; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 16:31 UTC (permalink / raw) To: Jagielski, Jedrzej, Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, chris.lew@oss.qualcomm.com, Deepak Kumar Singh On 14-07-2026 01:25 pm, Jagielski, Jedrzej wrote: > From: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> > Sent: Tuesday, July 14, 2026 7:33 AM > >> On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / >> NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces >> per-region access control, each individually DMA-mapped RX buffer >> requires its own XPU resource group (RG). With ~16 RGs available, the >> 32 per-buffer dma_map_single() calls exhaust the table and the first >> inbound transfer faults with an XPU violation. >> >> BAM-DMUX is a singleton (exactly one instance per SoC), so the >> destination VMID does not need to be a DT property; it is looked up > >from the compatible string's match data instead. Add struct >> bam_dmux_data with a single vmid field, and a shikra_data instance >> hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. >> >> When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as >> a single contiguous dma_alloc_coherent() block and SCM-assign that >> block to HLOS plus the VMID once at probe. This reduces RG consumption > >from 32 to 1. The block is never reclaimed across a modem power cycle >> (bam_dmux_power_off() does not touch it), so the probe-time assignment >> covers every subsequent restart without re-assigning or reclaiming. It >> is reclaimed to HLOS only once, at remove or on a probe error, and if >> that reclaim fails it is leaked rather than returned to the page >> allocator. >> >> Each rx_skbs[] slot is pre-assigned its virtual and DMA address from >> the block, so no per-buffer mapping is needed at power-on. Because the >> coherent block is not page-backed, received payload is copied into a >> regular netdev skb before handoff to the network stack; this is an >> unavoidable extra copy on the XPU-enforced RX path. >> >> Platforms without match data are unaffected: rx_virt stays NULL, no >> coherent memory is allocated, and the per-buffer dma_map_single() path >> is unchanged. >> >> Co-developed-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com> >> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> >> --- >> drivers/net/wwan/Kconfig | 1 + >> drivers/net/wwan/qcom_bam_dmux.c | 134 ++++++++++++++++++++++++++++++++++++--- >> 2 files changed, 125 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig >> index 958dbc7347fa84ee869439bf8b503037faab8bef..1b133c56231615269698140187ca3141dfe48dbf 100644 >> --- a/drivers/net/wwan/Kconfig >> +++ b/drivers/net/wwan/Kconfig >> @@ -65,6 +65,7 @@ config MHI_WWAN_MBIM >> config QCOM_BAM_DMUX >> tristate "Qualcomm BAM-DMUX WWAN network driver" >> depends on (DMA_ENGINE && PM && QCOM_SMEM_STATE) || COMPILE_TEST >> + select QCOM_SCM >> help >> The BAM Data Multiplexer provides access to the network data channels >> of modems integrated into many older Qualcomm SoCs, e.g. Qualcomm >> diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c >> index cc6ace8d64371eb8d00c638a39b234ee540b83c9..247230b720e6011876d5c429badbb5a1f34fc576 100644 >> --- a/drivers/net/wwan/qcom_bam_dmux.c >> +++ b/drivers/net/wwan/qcom_bam_dmux.c >> @@ -9,10 +9,12 @@ >> #include <linux/completion.h> >> #include <linux/dma-mapping.h> >> #include <linux/dmaengine.h> >> +#include <linux/firmware/qcom/qcom_scm.h> >> #include <linux/if_arp.h> >> #include <linux/interrupt.h> >> #include <linux/module.h> >> #include <linux/netdevice.h> >> +#include <linux/of.h> >> #include <linux/platform_device.h> >> #include <linux/pm_runtime.h> >> #include <linux/soc/qcom/smem_state.h> >> @@ -62,6 +64,7 @@ struct bam_dmux_skb_dma { >> struct bam_dmux *dmux; >> struct sk_buff *skb; >> dma_addr_t addr; >> + void *rx_virt; /* non-NULL: slot in the coherent RX block */ >> }; >> >> struct bam_dmux { >> @@ -75,6 +78,10 @@ struct bam_dmux { >> struct completion pc_ack_completion; >> >> struct dma_chan *rx, *tx; >> + /* Single coherent block backing all RX buffers, NULL if unused */ >> + void *rx_buf; >> + dma_addr_t rx_buf_dma; >> + u64 rx_buf_perms; /* SCM source-VMID bitmask of rx_buf */ >> struct bam_dmux_skb_dma rx_skbs[BAM_DMUX_NUM_SKB]; >> struct bam_dmux_skb_dma tx_skbs[BAM_DMUX_NUM_SKB]; >> spinlock_t tx_lock; /* Protect tx_skbs, tx_next_skb */ >> @@ -92,6 +99,10 @@ struct bam_dmux_netdev { >> u8 ch; >> }; >> >> +struct bam_dmux_data { >> + u32 vmid; >> +}; >> + > do we need to introduce dedicated struct just to cover u32? This is currently tied up in the open discussion on whether the VMID should come from match data or an optional qcom,vmid DT property instead. If match data stays, I agree a bare u32 value works without a dedicated struct and I'll simplify it that way. > >> static void bam_dmux_pc_vote(struct bam_dmux *dmux, bool enable) >> { >> reinit_completion(&dmux->pc_ack_completion); >> @@ -111,6 +122,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, >> { >> struct device *dev = skb_dma->dmux->dev; >> >> + if (skb_dma->rx_virt) /* coherent RX slot: addr pre-assigned */ >> + return true; >> + >> skb_dma->addr = dma_map_single(dev, skb_dma->skb->data, skb_dma->skb->len, dir); >> if (dma_mapping_error(dev, skb_dma->addr)) { >> dev_err(dev, "Failed to DMA map buffer\n"); >> @@ -124,6 +138,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, >> static void bam_dmux_skb_dma_unmap(struct bam_dmux_skb_dma *skb_dma, >> enum dma_data_direction dir) >> { >> + if (skb_dma->rx_virt) /* coherent RX slot: nothing to unmap */ >> + return; >> + >> dma_unmap_single(skb_dma->dmux->dev, skb_dma->addr, skb_dma->skb->len, dir); >> skb_dma->addr = 0; >> } >> @@ -468,9 +485,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) >> { >> struct bam_dmux *dmux = skb_dma->dmux; >> struct dma_async_tx_descriptor *desc; >> + size_t len = skb_dma->rx_virt ? BAM_DMUX_BUFFER_SIZE : skb_dma->skb->len; > please stick to RCT > please fix it here and for the following where RCT is violated I will fix all the declaration ordering in v2. > >> desc = dmaengine_prep_slave_single(dmux->rx, skb_dma->addr, >> - skb_dma->skb->len, DMA_DEV_TO_MEM, >> + len, DMA_DEV_TO_MEM, >> DMA_PREP_INTERRUPT); >> if (!desc) { >> dev_err(dmux->dev, "Failed to prepare RX DMA buffer\n"); >> @@ -485,6 +503,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) >> >> static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp) >> { >> + /* Coherent RX slots have rx_virt and addr pre-assigned at probe. */ >> + if (skb_dma->rx_virt) >> + return bam_dmux_skb_dma_submit_rx(skb_dma); >> + >> if (!skb_dma->skb) { >> skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp); >> if (!skb_dma->skb) >> @@ -499,9 +521,10 @@ static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gf >> static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) >> { >> struct bam_dmux *dmux = skb_dma->dmux; >> - struct sk_buff *skb = skb_dma->skb; >> - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; >> + struct bam_dmux_hdr *hdr = skb_dma->rx_virt ? skb_dma->rx_virt : >> + (struct bam_dmux_hdr *)skb_dma->skb->data; >> struct net_device *netdev = dmux->netdevs[hdr->ch]; >> + struct sk_buff *skb; >> >> if (!netdev || !netif_running(netdev)) { >> dev_warn(dmux->dev, "Data for inactive channel %u\n", hdr->ch); >> @@ -514,10 +537,18 @@ static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) >> return; >> } >> >> - skb_dma->skb = NULL; /* Hand over to network stack */ >> - >> - skb_pull(skb, sizeof(*hdr)); >> - skb_trim(skb, hdr->len); >> + if (skb_dma->rx_virt) { >> + /* Coherent block is not page-backed: copy out to a real skb */ >> + skb = netdev_alloc_skb(netdev, hdr->len); >> + if (!skb) >> + return; >> + skb_put_data(skb, (u8 *)skb_dma->rx_virt + sizeof(*hdr), hdr->len); >> + } else { >> + skb = skb_dma->skb; >> + skb_dma->skb = NULL; /* Hand over to network stack */ >> + skb_pull(skb, sizeof(*hdr)); >> + skb_trim(skb, hdr->len); >> + } >> skb->dev = netdev; >> >> /* Only Raw-IP/QMAP is supported by this driver */ >> @@ -574,10 +605,14 @@ static void bam_dmux_rx_callback(void *data) >> { >> struct bam_dmux_skb_dma *skb_dma = data; >> struct bam_dmux *dmux = skb_dma->dmux; >> - struct sk_buff *skb = skb_dma->skb; >> - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; >> + struct bam_dmux_hdr *hdr; >> >> - bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); >> + if (skb_dma->rx_virt) { >> + hdr = skb_dma->rx_virt; /* coherent RX: no skb to unmap */ >> + } else { >> + bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); >> + hdr = (struct bam_dmux_hdr *)skb_dma->skb->data; >> + } >> >> if (hdr->magic != BAM_DMUX_HDR_MAGIC) { >> dev_err(dmux->dev, "Invalid magic in header: %#x\n", hdr->magic); >> @@ -644,6 +679,9 @@ static void bam_dmux_free_skbs(struct bam_dmux_skb_dma skbs[], >> for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { >> struct bam_dmux_skb_dma *skb_dma = &skbs[i]; >> >> + if (skb_dma->rx_virt) /* coherent block freed at remove */ >> + continue; >> + >> if (skb_dma->addr) >> bam_dmux_skb_dma_unmap(skb_dma, dir); >> if (skb_dma->skb) { >> @@ -762,6 +800,71 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) >> return 0; >> } >> >> +static int bam_dmux_alloc_coherent_rx(struct bam_dmux *dmux) >> +{ >> + struct device *dev = dmux->dev; >> + const struct bam_dmux_data *data = of_device_get_match_data(dev); >> + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; >> + u64 src = BIT_ULL(QCOM_SCM_VMID_HLOS); >> + struct qcom_scm_vmperm dst[2]; >> + int i, ret; >> + >> + if (!data) >> + return 0; > is there actually any chance to really trigger that check? > or just theoretical case? Yes, it's reachable. The generic "qcom,bam-dmux" entry in bam_dmux_of_match[] has no .data, so any platform probing via that fallback compatible (i.e. every existing non-Shikra board using this driver today) gets NULL here and takes the unmodified per-buffer dma_map_single() path. This is the intended gate that keeps the new coherent-block allocation opt-in to Shikra only. > >> + >> + if (!qcom_scm_is_available()) >> + return -EPROBE_DEFER; >> + >> + dst[0].vmid = QCOM_SCM_VMID_HLOS; >> + dst[0].perm = QCOM_SCM_PERM_RW; >> + dst[1].vmid = data->vmid; >> + dst[1].perm = QCOM_SCM_PERM_RW; >> + >> + dmux->rx_buf = dma_alloc_coherent(dev, size, &dmux->rx_buf_dma, GFP_KERNEL); >> + if (!dmux->rx_buf) >> + return -ENOMEM; >> + >> + for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { >> + dmux->rx_skbs[i].rx_virt = dmux->rx_buf + i * BAM_DMUX_BUFFER_SIZE; >> + dmux->rx_skbs[i].addr = dmux->rx_buf_dma + i * BAM_DMUX_BUFFER_SIZE; >> + } >> + >> + ret = qcom_scm_assign_mem(dmux->rx_buf_dma, size, &src, dst, ARRAY_SIZE(dst)); >> + if (ret) { >> + dev_err(dev, "SCM assign RX block failed: %d\n", ret); >> + dma_free_coherent(dev, size, dmux->rx_buf, dmux->rx_buf_dma); >> + dmux->rx_buf = NULL; >> + return ret; >> + } >> + dmux->rx_buf_perms = src; >> + >> + return 0; >> +} >> + >> +static void bam_dmux_free_coherent_rx(struct bam_dmux *dmux) >> +{ >> + struct qcom_scm_vmperm hlos = { >> + .vmid = QCOM_SCM_VMID_HLOS, >> + .perm = QCOM_SCM_PERM_RW, >> + }; >> + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; >> + >> + if (!dmux->rx_buf) >> + return; >> + >> + if (dmux->rx_buf_perms) { >> + if (qcom_scm_assign_mem(dmux->rx_buf_dma, size, &dmux->rx_buf_perms, >> + &hlos, 1)) { >> + dev_err(dmux->dev, "SCM reclaim RX block failed; leaking\n"); >> + return; >> + } >> + dmux->rx_buf_perms = 0; >> + } >> + >> + dma_free_coherent(dmux->dev, size, dmux->rx_buf, dmux->rx_buf_dma); >> + dmux->rx_buf = NULL; >> +} >> + >> static int bam_dmux_probe(struct platform_device *pdev) >> { >> struct device *dev = &pdev->dev; >> @@ -809,6 +912,10 @@ static int bam_dmux_probe(struct platform_device *pdev) >> dmux->tx_skbs[i].dmux = dmux; >> } >> >> + ret = bam_dmux_alloc_coherent_rx(dmux); >> + if (ret) >> + return ret; >> + >> /* Runtime PM manages our own power vote. >> * Note that the RX path may be active even if we are runtime suspended, >> * since it is controlled by the remote side. >> @@ -845,6 +952,7 @@ static int bam_dmux_probe(struct platform_device *pdev) >> err_disable_pm: >> pm_runtime_disable(dev); >> pm_runtime_dont_use_autosuspend(dev); >> + bam_dmux_free_coherent_rx(dmux); >> return ret; >> } >> >> @@ -879,13 +987,19 @@ static void bam_dmux_remove(struct platform_device *pdev) >> disable_irq(dmux->pc_irq); >> bam_dmux_power_off(dmux); >> bam_dmux_free_skbs(dmux->tx_skbs, DMA_TO_DEVICE); >> + bam_dmux_free_coherent_rx(dmux); >> } >> >> static const struct dev_pm_ops bam_dmux_pm_ops = { >> SET_RUNTIME_PM_OPS(bam_dmux_runtime_suspend, bam_dmux_runtime_resume, NULL) >> }; >> >> +static const struct bam_dmux_data shikra_data = { >> + .vmid = QCOM_SCM_VMID_NAV, >> +}; >> + >> static const struct of_device_id bam_dmux_of_match[] = { >> + { .compatible = "qcom,shikra-bam-dmux", .data = &shikra_data }, >> { .compatible = "qcom,bam-dmux" }, >> { /* sentinel */ } >> }; >> >> -- >> 2.34.1 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 5:32 [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 5:32 ` [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible Vishnu Santhosh 2026-07-14 5:32 ` [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh @ 2026-07-14 7:53 ` Jagielski, Jedrzej 2026-07-14 16:08 ` Vishnu Santhosh 2 siblings, 1 reply; 11+ messages in thread From: Jagielski, Jedrzej @ 2026-07-14 7:53 UTC (permalink / raw) To: Vishnu Santhosh, Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, chris.lew@oss.qualcomm.com, Deepak Kumar Singh From: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> Sent: Tuesday, July 14, 2026 7:33 AM >On platforms where the modem DMAs into the BAM-DMUX RX data buffers and >the XPU (eXternal Protection Unit) enforces per-region access control, >each individually DMA-mapped RX buffer consumes an XPU resource group. >With only ~16 groups available on Shikra (mDSP, VMID 43 / NAV), the >per-buffer mappings exhaust the table and inbound transfers fault. > >This series adds a qcom,shikra-bam-dmux compatible and have the driver >select QCOM_SCM_VMID_NAV internally via that compatible's match data. >When matched, the driver allocates all RX buffers as a single >contiguous coherent block and SCM-assigns it to HLOS plus the VMID >once at probe, consuming one XPU resource group instead of many. > >Platforms that do not use the qcom,shikra-bam-dmux compatible are >unaffected: the existing per-buffer dma_map_single() path is >unchanged. > >Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> >--- >Vishnu Santhosh (2): > dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible > net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block > > .../devicetree/bindings/net/qcom,bam-dmux.yaml | 8 +- > drivers/net/wwan/Kconfig | 1 + > drivers/net/wwan/qcom_bam_dmux.c | 134 +++++++++++++++++++-- > 3 files changed, 132 insertions(+), 11 deletions(-) >--- >base-commit: 3b029c035b34bbc693405ddf759f0e9b920c27f1 >change-id: 20260714-qcom-bam-dmux-vmid-ext-d9289db310c1 > >Best regards, >-- >Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> Hi Vishnu you need to specify target tree, net-next for this series i believe please refer to[1] [1] https://docs.kernel.org/process/maintainer-netdev.html#indicating-target-tree ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block 2026-07-14 7:53 ` [PATCH 0/2] " Jagielski, Jedrzej @ 2026-07-14 16:08 ` Vishnu Santhosh 0 siblings, 0 replies; 11+ messages in thread From: Vishnu Santhosh @ 2026-07-14 16:08 UTC (permalink / raw) To: Jagielski, Jedrzej, Stephan Gerhold, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Loic Poulain, Sergey Ryazanov, Johannes Berg Cc: linux-arm-msm@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, chris.lew@oss.qualcomm.com, Deepak Kumar Singh On 14-07-2026 01:23 pm, Jagielski, Jedrzej wrote: > From: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> > Sent: Tuesday, July 14, 2026 7:33 AM > >> On platforms where the modem DMAs into the BAM-DMUX RX data buffers and >> the XPU (eXternal Protection Unit) enforces per-region access control, >> each individually DMA-mapped RX buffer consumes an XPU resource group. >> With only ~16 groups available on Shikra (mDSP, VMID 43 / NAV), the >> per-buffer mappings exhaust the table and inbound transfers fault. >> >> This series adds a qcom,shikra-bam-dmux compatible and have the driver >> select QCOM_SCM_VMID_NAV internally via that compatible's match data. >> When matched, the driver allocates all RX buffers as a single >> contiguous coherent block and SCM-assigns it to HLOS plus the VMID >> once at probe, consuming one XPU resource group instead of many. >> >> Platforms that do not use the qcom,shikra-bam-dmux compatible are >> unaffected: the existing per-buffer dma_map_single() path is >> unchanged. >> >> Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> >> --- >> Vishnu Santhosh (2): >> dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible >> net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block >> >> .../devicetree/bindings/net/qcom,bam-dmux.yaml | 8 +- >> drivers/net/wwan/Kconfig | 1 + >> drivers/net/wwan/qcom_bam_dmux.c | 134 +++++++++++++++++++-- >> 3 files changed, 132 insertions(+), 11 deletions(-) >> --- >> base-commit: 3b029c035b34bbc693405ddf759f0e9b920c27f1 >> change-id: 20260714-qcom-bam-dmux-vmid-ext-d9289db310c1 >> >> Best regards, >> -- >> Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com> > Hi Vishnu > you need to specify target tree, net-next for this series i believe > please refer to[1] > > [1] > https://docs.kernel.org/process/maintainer-netdev.html#indicating-target-tree > Thanks Jedrzej. I will address the comments and will send out the next revision specifying the target tree as net-next. Thanks, Vishnu ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-07-14 16:31 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-14 5:32 [PATCH 0/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 5:32 ` [PATCH 1/2] dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible Vishnu Santhosh 2026-07-14 7:11 ` Stephan Gerhold 2026-07-14 14:03 ` Vishnu Santhosh 2026-07-14 5:32 ` [PATCH 2/2] net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block Vishnu Santhosh 2026-07-14 7:35 ` Stephan Gerhold 2026-07-14 15:47 ` Vishnu Santhosh 2026-07-14 7:55 ` Jagielski, Jedrzej 2026-07-14 16:31 ` Vishnu Santhosh 2026-07-14 7:53 ` [PATCH 0/2] " Jagielski, Jedrzej 2026-07-14 16:08 ` Vishnu Santhosh
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox