[PATCH v2 3/3] drm/msm: detach the ARM DMA mapping before attaching our own domain
Dmitry Baryshkov <[email protected]> Thu, 30 Jul 2026 19:04:56 +0300
| Newsgroups | dev.linux.lists.iommu,org.freedesktop.lists.dri-devel,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-rockchip,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On ARM32 with CONFIG_ARM_DMA_USE_IOMMU, arch_setup_dma_ops() creates a dma_iommu_mapping for every IOMMU-backed device and attaches its domain to the device's IOMMU group. That domain is neither the group's default nor its blocking domain, so when msm_iommu_new() later attaches the domain the driver manages itself, __iommu_attach_group() refuses it: if (group->domain && group->domain != group->default_domain && group->domain != group->blocking_domain) return -EBUSY; Both the GPU and the display controller are hit by this on apq8064 (IFC6410), leaving the board with no GPU and no display: adreno 4300000.gpu: failed to load adreno gpu adreno 4300000.gpu: probe with driver adreno failed with error -16 mdp4 5100000.display-controller: [drm:msm_drm_kms_init] *ERROR* failed to load kms mdp4 5100000.display-controller: adev bind failed: -16 Other ARM32 DRM drivers that manage their own domains (tegra, rockchip, exynos) drop the arch mapping first. Do the same in msm_iommu_new(), which both the display and the GPU paths go through. With this the GPU and the KMS device both initialise: [drm] Initialized msm 1.13.0 for 4300000.gpu on minor 0 [drm] Initialized msm-kms 1.13.0 for 5100000.display-controller on minor 1 Assisted-by: Claude:claude-opus-5 Reviewed-by: Konrad Dybcio <[email protected]> Signed-off-by: Dmitry Baryshkov <[email protected]> --- drivers/gpu/drm/msm/msm_iommu.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 897e42c8d5c8..da6782fca6bd 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -7,6 +7,15 @@ #include <linux/adreno-smmu-priv.h> #include <linux/io-pgtable.h> #include <linux/kmemleak.h> + +#if defined(CONFIG_ARM_DMA_USE_IOMMU) +#include <asm/dma-iommu.h> +#else +#define arm_iommu_detach_device(...) ({ }) +#define arm_iommu_release_mapping(...) ({ }) +#define to_dma_iommu_mapping(dev) NULL +#endif + #include "msm_drv.h" #include "msm_gpu_trace.h" #include "msm_mmu.h" @@ -749,6 +758,19 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) mutex_init(&iommu->init_lock); + /* + * ARM32 attaches a DMA mapping domain to every IOMMU-backed device, + * which would make attaching our own domain fail with -EBUSY. + */ + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); + + if (mapping) { + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); + } + } + ret = iommu_attach_device(iommu->domain, dev); if (ret) { iommu_domain_free(domain); -- 2.47.3