.../iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 4 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 7 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 265 ++++++++++++++++----- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 34 ++- 4 files changed, 247 insertions(+), 63 deletions(-)
Some SoCs have a limited number of IOMMU Stream IDs (SIDs) and
hardware that inherently shares them. For example, the NXP i.MX95
eDMA controller has 64 channels where each TX/RX pair is assigned
a single SID by the hardware - the two channel devices are distinct
from Linux's perspective but present the same SID to the SMMU.
The current ARM SMMUv3 driver rejects this with:
"Aliasing StreamID unsupported, expect DMA to be broken"
I took comments in [1] and implement this patchset and only want to
support a very simple case that multiple platform devices share one SID.
This series adds support for multiple masters to share a single
SID, allowing per-channel DMA devices behind an IOMMU without
requiring one SID per channel.
Patch 1 converts the streams RB tree to an XArray for O(1) SID
lookup, simplifying duplicate-SID handling.
Patch 2 adds reference counting to streams so that multiple
masters can share a SID. Insert increments the refcount; remove
either transfers ownership or decrements. A per-SID linked list
tracks co-sharing masters.
Patch 3 places devices that share a SID into the same IOMMU
group, ensuring they share a single IOMMU domain.
Patch 4 wires up STE write ordering (first master writes, last
master tears down) and gates features that require unambiguous
SID-to-device mapping: SVA, IOPF/stall, and vSMMU nesting are
disabled for shared-SID masters.
[1] https://lore.kernel.org/linux-iommu/DU0PR04MB94172CB3F138AD39E9B6DEEF887F9@DU0PR04MB9417.eurprd04.prod.outlook.com/
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Peng Fan (4):
iommu/arm-smmu-v3: Convert streams from RB tree to XArray
iommu/arm-smmu-v3: Support shared SIDs in insert/remove_master
iommu/arm-smmu-v3: Group aliasing devices into the same IOMMU group
iommu/arm-smmu-v3: Wire up shared-SID STE ordering and feature gating
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 4 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 7 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 265 ++++++++++++++++-----
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 34 ++-
4 files changed, 247 insertions(+), 63 deletions(-)
---
base-commit: e6e35979777d646fe3c7c94dca7dd32fb25d45f4
change-id: 20260916-smmu-shared-sid-e488f6c4d4f0
Best regards,
--
Peng Fan <peng.fan@nxp.com>
On Wed, Sep 16, 2026 at 11:12:33PM +0800, Peng Fan (OSS) wrote: > Some SoCs have a limited number of IOMMU Stream IDs (SIDs) and > hardware that inherently shares them. For example, the NXP i.MX95 > eDMA controller has 64 channels where each TX/RX pair is assigned > a single SID by the hardware - the two channel devices are distinct > from Linux's perspective but present the same SID to the SMMU. Is that a reflection of poor DT modelling though? Why must a TX/RX *PAIR* have two platform_devices nodes? Fix it there and you don't need any of this? Or is there more? Jason
Hi Jason,
On Wed, Sep 16, 2026 at 01:10:18PM -0300, Jason Gunthorpe wrote:
>On Wed, Sep 16, 2026 at 11:12:33PM +0800, Peng Fan (OSS) wrote:
>> Some SoCs have a limited number of IOMMU Stream IDs (SIDs) and
>> hardware that inherently shares them. For example, the NXP i.MX95
>> eDMA controller has 64 channels where each TX/RX pair is assigned
>> a single SID by the hardware - the two channel devices are distinct
>> from Linux's perspective but present the same SID to the SMMU.
>
>Is that a reflection of poor DT modelling though?
>
>Why must a TX/RX *PAIR* have two platform_devices nodes?
>
>Fix it there and you don't need any of this? Or is there more?
I think there may be a misunderstanding about the device topology here.
There is only one platform device node for the eDMA controller
(dma-controller@42000000). There are no separate platform device nodes per
channel pair.
What happens instead:
The fsl-edma driver probes the single platform device. During
dmaenginem_async_device_register(), the dmaengine core calls
__dma_async_device_channel_register() for each channel, which creates a
struct dma_chan_dev containing a struct device - registered via
device_register() with class = &dma_devclass and parent = edma_platform_dev
(see drivers/dma/dmaengine.c line 1115-1125)
For a 64-channel eDMA, this creates 64 channel devices: dma0chan[0-63]
These channel devices are not platform devices. They are class devices under
the dma device class. They have no DT node, no of_node. They are purely
software constructs created by the dmaengine framework.
The iommu-map property sits on the eDMA controller's DT node. At channel
allocation time (xlate), the driver calls of_dma_configure_id(chan_dev,
edma_np, true, &chan_id) to look up the channel index in the eDMA node's
iommu-map and attach an IOMMU domain to that specific channel device. The
dmaengine framework's dmaengine_get_dma_device() API
(which checks chan->dev->chan_dma_dev) then returns the per-channel device
instead of the parent platform device, so DMA clients map buffers through
the correct IOMMU context.
The shared-SID situation arises because in hardware, each TX/RX channel
pair presents the same Stream ID to the SMMU. So dma0chan0 and dma0chan1
both get configured with SID 0x30 via:
iommu-map = <2 &smmu 0x30 1>,
<3 &smmu 0x30 1>,
...
Both channel devices end up in the same IOMMU group, but currently the SMMU
driver rejects the second device trying to register the same SID. That is
what this series fixes.
And merging TX and RX into a single channel device is not possible -
the dmaengine framework allocates one dma_chan (and thus one dma_chan_dev) per
direction. SPI/I2C/UART clients call dma_request_chan() separately
for "tx" and "rx", each returning an independent channel with its own device.
The two channels have different source ids (e.g. 83 for TX, 84 for RX) and
are independently programmable hardware resources - they only share a SID per
hardware design.
one more point to support SID sharing is that i.MX95 only support 64 SIDs,
however there are more than 64 DMA initiators.
Hope this explains well.
Thanks,
Peng
>
>Jason
>
>
On Thu, Sep 17, 2026 at 09:33:55AM +0800, Peng Fan wrote: > Hi Jason, > > On Wed, Sep 16, 2026 at 01:10:18PM -0300, Jason Gunthorpe wrote: > >On Wed, Sep 16, 2026 at 11:12:33PM +0800, Peng Fan (OSS) wrote: > >> Some SoCs have a limited number of IOMMU Stream IDs (SIDs) and > >> hardware that inherently shares them. For example, the NXP i.MX95 > >> eDMA controller has 64 channels where each TX/RX pair is assigned > >> a single SID by the hardware - the two channel devices are distinct > >> from Linux's perspective but present the same SID to the SMMU. > > > >Is that a reflection of poor DT modelling though? > > > >Why must a TX/RX *PAIR* have two platform_devices nodes? > > > >Fix it there and you don't need any of this? Or is there more? > > I think there may be a misunderstanding about the device topology here. > > There is only one platform device node for the eDMA controller > (dma-controller@42000000). There are no separate platform device nodes per > channel pair. > > What happens instead: > The fsl-edma driver probes the single platform device. During > dmaenginem_async_device_register(), the dmaengine core calls Yes, and if your DT is correct then that platform device should have a single iommus = [] listing all the SIDs for that logical device. Using iommu-map to describe synthetic dma_chan_dev devices that the kernel creates is the same kind of DT abuse from over here: https://lore.kernel.org/linux-iommu/20260618151745.GD231643@ziepe.ca/ So the problem is self created, by using iommu-map instead of iommus and using DT to describe linux SW expectations you end up in this strange place of asking for aliases. > The iommu-map property sits on the eDMA controller's DT node. At channel > allocation time (xlate), the driver calls of_dma_configure_id(chan_dev, > edma_np, true, &chan_id) to look up the channel index in the eDMA node's > iommu-map and attach an IOMMU domain to that specific channel device. The > dmaengine framework's dmaengine_get_dma_device() API > (which checks chan->dev->chan_dma_dev) then returns the per-channel device > instead of the parent platform device, so DMA clients map buffers through > the correct IOMMU context. So go back to the basics, why did this platform use iommu-map instead of iommus? The only real difference is you get a DMA translation per queue. Is that required? Are you short IOVA? Some other reason? You can read what I wrote about this general problem before: https://lore.kernel.org/linux-iommu/20260818130724.GA5482@ziepe.ca/ It would be really nice if you all could work together to figure out a better way to handle this than through DT abuses. If you really need unique translations per sub-compoment of a logical device from some pool of SIDs that feels like a weird version of PASID to me, it may be an interesting to explore. Jason
Hi Jason, On Thu, Sep 17, 2026 at 11:48:04AM -0300, Jason Gunthorpe wrote: >On Thu, Sep 17, 2026 at 09:33:55AM +0800, Peng Fan wrote: >> Hi Jason, >> >> On Wed, Sep 16, 2026 at 01:10:18PM -0300, Jason Gunthorpe wrote: >> >On Wed, Sep 16, 2026 at 11:12:33PM +0800, Peng Fan (OSS) wrote: >> >> Some SoCs have a limited number of IOMMU Stream IDs (SIDs) and >> >> hardware that inherently shares them. For example, the NXP i.MX95 >> >> eDMA controller has 64 channels where each TX/RX pair is assigned >> >> a single SID by the hardware - the two channel devices are distinct >> >> from Linux's perspective but present the same SID to the SMMU. >> > >> >Is that a reflection of poor DT modelling though? >> > >> >Why must a TX/RX *PAIR* have two platform_devices nodes? >> > >> >Fix it there and you don't need any of this? Or is there more? >> >> I think there may be a misunderstanding about the device topology here. >> >> There is only one platform device node for the eDMA controller >> (dma-controller@42000000). There are no separate platform device nodes per >> channel pair. >> >> What happens instead: >> The fsl-edma driver probes the single platform device. During >> dmaenginem_async_device_register(), the dmaengine core calls > >Yes, and if your DT is correct then that platform device should have a >single iommus = [] listing all the SIDs for that logical device. Agreed - the DMA controller should use iommus, not iommu-map. I'll rework the DT side. The iommu-map approach has not landed upstream, so nothing is set in stone yet. > >Using iommu-map to describe synthetic dma_chan_dev devices that the >kernel creates is the same kind of DT abuse from over here: > Thanks for sharing the links. >https://lore.kernel.org/linux-iommu/20260618151745.GD231643@ziepe.ca/ Per reading this thread, seems need to describe VPU sub-blocks blocks using device tree node. For NXP i.MX95, we just use one device tree node for the DMA controller. https://elixir.bootlin.com/linux/v7.2.5/source/arch/arm64/boot/dts/freescale/imx95.dtsi#L634 > >So the problem is self created, by using iommu-map instead of iommus >and using DT to describe linux SW expectations you end up in this >strange place of asking for aliases. The iommu-map DT property is not landed in upstream, it is still under reviewing. https://lore.kernel.org/dmaengine/20260916-edma-iommu-v1-1-e1731968081e@nxp.com/ > >> The iommu-map property sits on the eDMA controller's DT node. At channel >> allocation time (xlate), the driver calls of_dma_configure_id(chan_dev, >> edma_np, true, &chan_id) to look up the channel index in the eDMA node's >> iommu-map and attach an IOMMU domain to that specific channel device. The >> dmaengine framework's dmaengine_get_dma_device() API >> (which checks chan->dev->chan_dma_dev) then returns the per-channel device >> instead of the parent platform device, so DMA clients map buffers through >> the correct IOMMU context. > >So go back to the basics, why did this platform use iommu-map instead >of iommus? The only real difference is you get a DMA translation per >queue. Is that required? Are you short IOVA? Some other reason? No, per-queue translation is not required. A single iommus entry (or a list of all SIDs the controller uses) on the platform device would work. I'll take this direction. > >You can read what I wrote about this general problem before: > >https://lore.kernel.org/linux-iommu/20260818130724.GA5482@ziepe.ca/ > >It would be really nice if you all could work together to figure out a >better way to handle this than through DT abuses. Understood. I'll follow up on the links you shared and work with the dmaengine folks to sort out the DT modelling. However, the DMA channel case was just one example - the shared-SID need exists independently of it. Our SoC (i.MX95) has only 64 SIDs total, serving MMC, SD, NET, PCI, DMA, NPU, DSP, DISPLAY and more. Some of these are genuinely separate platform devices (distinct DT nodes, distinct drivers) that share a SID by hardware design because the SID space is exhausted. That cross-IP case cannot be solved by DT restructuring - the devices really are separate. Would you be open to reviewing the shared-SID SMMU support (patches 1-4) on that basis, independent of the DMA channel question? Thanks, Peng > >If you really need unique translations per sub-compoment of a logical >device from some pool of SIDs that feels like a weird version of PASID >to me, it may be an interesting to explore. > >Jason > >
On Fri, Sep 18, 2026 at 07:48:34PM +0800, Peng Fan wrote: > However, the DMA channel case was just one example - the shared-SID > need exists independently of it. Our SoC (i.MX95) has only 64 SIDs > total, serving MMC, SD, NET, PCI, DMA, NPU, DSP, DISPLAY and more. > Some of these are genuinely separate platform devices (distinct DT > nodes, distinct drivers) that share a SID by hardware design because > the SID space is exhausted. > > That cross-IP case cannot be solved by DT restructuring - the devices > really are separate. Would you be open to reviewing the shared-SID > SMMU support (patches 1-4) on that basis, independent of the DMA > channel question? I think you should revise your commit message/cover letter to focus on something that is not a DT abuse and try again IIRC Robin said the SID aliasing was a PITA on SMMUv2 so it really needs to have a strong reason. Jason
On Fri, Sep 18, 2026 at 09:11:32AM -0300, Jason Gunthorpe wrote: >On Fri, Sep 18, 2026 at 07:48:34PM +0800, Peng Fan wrote: > >> However, the DMA channel case was just one example - the shared-SID >> need exists independently of it. Our SoC (i.MX95) has only 64 SIDs >> total, serving MMC, SD, NET, PCI, DMA, NPU, DSP, DISPLAY and more. >> Some of these are genuinely separate platform devices (distinct DT >> nodes, distinct drivers) that share a SID by hardware design because >> the SID space is exhausted. >> >> That cross-IP case cannot be solved by DT restructuring - the devices >> really are separate. Would you be open to reviewing the shared-SID >> SMMU support (patches 1-4) on that basis, independent of the DMA >> channel question? > >I think you should revise your commit message/cover letter to focus on >something that is not a DT abuse and try again Yes. I will prepare RFC V2 with revised cover letter. > >IIRC Robin said the SID aliasing was a PITA on SMMUv2 so it >really needs to have a strong reason. Not like sever/data center chips, i.MX95 does not the advanced features, so in [PATCH RFC 4/4], those advanced features are marked as not supported. In the chip internal bus, there are only 6 bits are used to carry SID on the bus, so limited SIDs. Hope we could move forward to support just simple SID sharing between platform devices without advancing features. Thanks, Peng > >Jason > >
© 2016 - 2026 Red Hat, Inc.