* [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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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
1 sibling, 0 replies; 8+ 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] 8+ 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
2 siblings, 0 replies; 8+ 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] 8+ 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
1 sibling, 0 replies; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread
end of thread, other threads:[~2026-07-14 14:03 UTC | newest]
Thread overview: 8+ 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 7:55 ` Jagielski, Jedrzej
2026-07-14 7:53 ` [PATCH 0/2] " Jagielski, Jedrzej
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox