rockchip_gem_prime_import_sg_table() uses iommu_map_sgtable(), which reads
CPU-side pages and lengths. DMABUF_DEBUG clears these fields, causing
the RK3588 import failures reported by Diederik de Haas.

The attachment's DMA addresses belong to the VOP's default domain,
while scanout uses a separate DRM domain. Use iommu_map_sgtable_dma()
to copy the live mapping into that domain.

Keep native allocations unchanged. Unsupported imports still use the
old page-based path and remain unfixed under strict DMABUF_DEBUG.
This RFC retains reverse translation rather than sharing the DMA domain.

Reported-by: Diederik de Haas <[email protected]>
Link: https://lore.kernel.org/r/[email protected]/
Link: https://lore.kernel.org/r/[email protected]/
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <[email protected]>
---
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 9a1dc9f12072..501c94cb921a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -20,7 +20,8 @@
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 
-static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj)
+static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj,
+                                 struct device *dma_dev)
 {
        struct drm_device *drm = rk_obj->base.dev;
        struct rockchip_drm_private *private = drm->dev_private;
@@ -40,8 +41,16 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object 
*rk_obj)
 
        rk_obj->dma_addr = rk_obj->mm.start;
 
-       ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt,
-                               prot);
+       if (dma_dev) {
+               ret = iommu_map_sgtable_dma(private->domain, rk_obj->dma_addr,
+                                           dma_dev, rk_obj->sgt, prot);
+               if (ret == -EOPNOTSUPP)
+                       ret = iommu_map_sgtable(private->domain, 
rk_obj->dma_addr,
+                                               rk_obj->sgt, prot);
+       } else {
+               ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr,
+                                       rk_obj->sgt, prot);
+       }
        if (ret < (ssize_t)rk_obj->base.size) {
                DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n",
                          ret, rk_obj->base.size);
@@ -131,7 +140,7 @@ static int rockchip_gem_alloc_iommu(struct 
rockchip_gem_object *rk_obj,
        if (ret < 0)
                return ret;
 
-       ret = rockchip_gem_iommu_map(rk_obj);
+       ret = rockchip_gem_iommu_map(rk_obj, NULL);
        if (ret < 0)
                goto err_free;
 
@@ -457,7 +466,7 @@ rockchip_gem_iommu_map_sg(struct drm_device *drm,
                          struct rockchip_gem_object *rk_obj)
 {
        rk_obj->sgt = sg;
-       return rockchip_gem_iommu_map(rk_obj);
+       return rockchip_gem_iommu_map(rk_obj, attach->dev);
 }
 
 static int
-- 
2.53.0

Reply via email to