Devicetree
 help / color / mirror / Atom feed
* [PATCH v3 0/7] dmaengine: add DMA channel bus and fsl-edma per-channel IOMMU support
@ 2026-11-02  6:49 Peng Fan (OSS)
  2026-11-02  6:49 ` [PATCH v3 1/7] dmaengine: fsl-edma: unregister channels before vchan cleanup Peng Fan (OSS)
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Peng Fan (OSS) @ 2026-11-02  6:49 UTC (permalink / raw)
  To: Frank Li, Vinod Koul, Joerg Roedel (AMD), Will Deacon,
	Robin Murphy, Laxman Dewangan, Jon Hunter, Thierry Reding,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam
  Cc: Frank Li, Larisa IIeana Grigore, imx, dmaengine, linux-kernel,
	iommu, linux-tegra, devicetree, linux-arm-kernel, Peng Fan

I used iommu-map for eDMA, but iommu experts rejected it:
"Using iommu-map to describe synthetic dma_chan_dev devices that the
kernel creates is the same kind of DT abuse from over here:"
More info: https://lore.kernel.org/all/20260917144804.GI3196566@ziepe.ca/

So I followed here [2] as Krzysztof wrote for QCOM VPU:
"Thanks Jason for context and detailed arguments. Robin did not chime in
yet, but from what I understood the DT-child-node approach will be the
way we should go here.

I accept above point of view and I am fine with this, thus Vishnu and
Vikash - please go ahead with DT-child-node solution we had some time ago."
[2] https://lore.kernel.org/linux-iommu/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/

This series adds per-channel DT child node support to fsl-edma and, as a
prerequisite, introduces a proper bus for DMA channel devices.

The fsl-edma change allows each channel to carry its own reg, interrupts,
iommus and power-domains properties. Parsing the child nodes is
straightforward, but per-channel IOMMU configuration is not: the DMA engine
currently creates struct dma_chan_dev as a class device without any bus, so
of_dma_configure() has no bus to probe the IOMMU with, and the IOMMU core
does not have a bus notifier for DMA channel devices.

Drivers that need per-channel IOMMU support currently work around this by
assigning dev->bus after dmaenginem_async_device_register().  That is unsafe
because bus_add_device() already ran with bus == NULL and did not take a bus
subsystem reference.  When the channel device is later unregistered,
bus_remove_device() drops a reference that was never acquired, leading to a
reference count underflow and a potential use-after-free.  Using
platform_bus_type is also wrong: platform_match() and platform_uevent()
expect the device to be embedded in a struct platform_device.

A dedicated bus for DMA channel devices solves this.  The channel devices are
converted from class devices to bus devices:

  - the bus is registered early, before iommu_subsys_init() consumes
    iommu_buses[];
  - the match callback always reports no match, so no driver binds to a
    channel device;
  - channel devices are registered on the bus before device_register(), so
    bus_add_device() and bus_remove_device() are balanced;
  - the bus is added to iommu_buses[], so the existing IOMMU notifier
    handles per-channel IOMMU probe and release.

The existing /sys/class/dma interface is preserved with class_compat, the
mechanism provided by the driver core for converting a class device family to
bus devices. A compatibility class named "dma" keeps
/sys/class/dma/dmaNchanM available, while the devices themselves live on the
DMA bus. The uevent subsystem name remains "dma" because the bus has the same
name as the old class. dma_dev_groups moves from the old class to the bus,
and chan_dev_release is installed directly as the device release callback.

While testing controller unbind, a pre-existing fsl-edma ordering bug was
found: fsl_edma_remove() removed all channels from dma_dev.channels before the
managed dma_async_device_unregister() action ran, so the channel devices and
their IOMMU groups were never released. Patch 1 fixes that ordering, which is
needed to make the bind/unbind lifecycle test meaningful.

Patch breakdown

1/7 dmaengine: fsl-edma: unregister channels before vchan cleanup

    Keep the vchan cleanup, but run it from a devres action that is ordered
    after the managed dma_async_device_unregister().  This restores proper
    channel device and IOMMU group removal on controller unbind.

2/7 dmaengine: add a bus for DMA channel devices

    Add dma_chan_bus_type and register it from dma_bus_init().  The match
    callback never matches.  There is no functional change yet.

3/7 iommu: register the DMA channel bus for IOMMU notifications

    Add dma_chan_bus_type to iommu_buses[] under CONFIG_DMA_ENGINE.
    dma_bus_init() is an arch_initcall and runs before iommu_subsys_init(),
    so the bus is registered before the IOMMU core consumes iommu_buses[].

4/7 dmaengine: move channel devices to the DMA channel bus

    Register each dma_chan_dev on the DMA bus before device_register(),
    install the release callback directly, attach dma_dev_groups to the bus,
    and switch the /sys/class/dma view to class_compat.  Remove the manual
    post-registration bus assignment from the Tegra GPC DMA driver.

5/7 dt-bindings: dma: fsl,edma: add per-channel child node support

    Document optional dma-channel@<addr> child nodes with reg, interrupts,
    iommus and power-domains properties.

6/7 dmaengine: fsl-edma: support per-channel DT child nodes

    Derive the channel index from the child MMIO address, populate the
    per-channel IRQ, propagate -EPROBE_DEFER from of_irq_get(), and
    configure the per-channel IOMMU on the channel device using
    of_dma_configure().  Existing DTS without child nodes keeps working.

7/7 arm64: dts: imx95: convert eDMA to per-channel child nodes

    Describe the per-channel register regions and interrupts for i.MX95
    eDMA.  The iommus properties are not added yet; they will be submitted
    separately once the stream ID assignment is finalized.

The only user-visible change from the bus introduction is that the device's
"subsystem" link now points to /sys/bus/dma instead of /sys/class/dma. The
/sys/class/dma/dmaNchanM path itself is unchanged, and both the bus and the
compatibility class are named "dma".

Patches 2-4 can be merged separately if preferred, but the fsl-edma patches
depend on them. Patch 6 deliberately does not touch dev->bus; it relies on
the DMA engine core registering the channel device on the DMA channel bus.

The binding and driver support per-channel iommus, but patch 7 does not add
them to the i.MX95 DTS yet. That DT update will be sent separately when the
shared stream ID support are finalized.

I put all the patches in one patchset to give people a full picture.
If need to separate patches into multiple patchsets, I could do that
in next version.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Changes in V3:
- Patch [1-4] are new patches
- Add R-b for patch 5
- Patch 6: handle of_irq_get() -EPROBE_DEFER, drop the explicit bus
  assignment to "chdev->bus" which is resolved by patch [2-4].
- Rebased to linus/master v7.4-rc1
Changes in V2:
- Switch to add child node for dma channel.
- Link to V1: https://lore.kernel.org/dmaengine/20260916-edma-iommu-v1-0-e1731968081e@nxp.com/

---
Peng Fan (7):
      dmaengine: fsl-edma: unregister channels before vchan cleanup
      dmaengine: add a bus for DMA channel devices
      iommu: register the DMA channel bus for IOMMU notifications
      dmaengine: move channel devices to the DMA channel bus
      dt-bindings: dma: fsl,edma: add per-channel child node support
      dmaengine: fsl-edma: support per-channel DT child nodes
      arm64: dts: imx95: convert eDMA to per-channel child nodes

 .../devicetree/bindings/dma/fsl,edma.yaml          |  70 +-
 arch/arm64/boot/dts/freescale/imx95.dtsi           | 774 +++++++++++++++++----
 drivers/dma/dmaengine.c                            |  43 +-
 drivers/dma/fsl-edma-common.c                      |  10 +-
 drivers/dma/fsl-edma-main.c                        | 164 ++++-
 drivers/dma/tegra186-gpc-dma.c                     |   1 -
 drivers/iommu/iommu.c                              |   4 +
 include/linux/dmaengine.h                          |   4 +
 8 files changed, 919 insertions(+), 151 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261102-edma-iommu-v3-22b673717cf4

Best regards,
--  
OpenCode Assistant <opencode@Example.Com>


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-11-02  7:10 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02  6:49 [PATCH v3 0/7] dmaengine: add DMA channel bus and fsl-edma per-channel IOMMU support Peng Fan (OSS)
2026-11-02  6:49 ` [PATCH v3 1/7] dmaengine: fsl-edma: unregister channels before vchan cleanup Peng Fan (OSS)
2026-11-02  6:49 ` [PATCH v3 2/7] dmaengine: add a bus for DMA channel devices Peng Fan (OSS)
2026-11-02  7:02   ` sashiko-bot
2026-11-02  6:49 ` [PATCH v3 3/7] iommu: register the DMA channel bus for IOMMU notifications Peng Fan (OSS)
2026-11-02  7:03   ` sashiko-bot
2026-11-02  6:49 ` [PATCH v3 4/7] dmaengine: move channel devices to the DMA channel bus Peng Fan (OSS)
2026-11-02  6:49 ` [PATCH v3 5/7] dt-bindings: dma: fsl,edma: add per-channel child node support Peng Fan (OSS)
2026-11-02  6:50 ` [PATCH v3 6/7] dmaengine: fsl-edma: support per-channel DT child nodes Peng Fan (OSS)
2026-11-02  7:10   ` sashiko-bot
2026-11-02  6:50 ` [PATCH v3 7/7] arm64: dts: imx95: convert eDMA to per-channel " Peng Fan (OSS)
2026-11-02  7:00   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox