]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/msm: Add mmu support for non-zero offset
authorRob Clark <robdclark@chromium.org>
Sun, 29 Jun 2025 20:13:00 +0000 (13:13 -0700)
committerRob Clark <robin.clark@oss.qualcomm.com>
Sat, 5 Jul 2025 00:48:35 +0000 (17:48 -0700)
Only needs to be supported for iopgtables mmu, the other cases are
either only used for kernel managed mappings (where offset is always
zero) or devices which do not support sparse bindings.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
Tested-by: Antonino Maniscalco <antomani103@gmail.com>
Reviewed-by: Antonino Maniscalco <antomani103@gmail.com>
Patchwork: https://patchwork.freedesktop.org/patch/661501/

drivers/gpu/drm/msm/adreno/a2xx_gpummu.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gem_vma.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/msm/msm_mmu.h

index 4280f71e472a4130a62ba74e936870905ca260bb..0407c9bc8c1bf45688f1dc9b924435a590a587af 100644 (file)
@@ -29,13 +29,16 @@ static void a2xx_gpummu_detach(struct msm_mmu *mmu)
 }
 
 static int a2xx_gpummu_map(struct msm_mmu *mmu, uint64_t iova,
-               struct sg_table *sgt, size_t len, int prot)
+                          struct sg_table *sgt, size_t off, size_t len,
+                          int prot)
 {
        struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
        unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
        struct sg_dma_page_iter dma_iter;
        unsigned prot_bits = 0;
 
+       WARN_ON(off != 0);
+
        if (prot & IOMMU_WRITE)
                prot_bits |= 1;
        if (prot & IOMMU_READ)
index 20d5e4b4d057fca0cb7fe6b6c2023043e1ba1434..5c71a4be0dfafb82a648b850da0d090df1bac8e4 100644 (file)
@@ -453,7 +453,7 @@ static struct drm_gpuva *get_vma_locked(struct drm_gem_object *obj,
        vma = lookup_vma(obj, vm);
 
        if (!vma) {
-               vma = msm_gem_vma_new(vm, obj, range_start, range_end);
+               vma = msm_gem_vma_new(vm, obj, 0, range_start, range_end);
        } else {
                GEM_WARN_ON(vma->va.addr < range_start);
                GEM_WARN_ON((vma->va.addr + obj->size) > range_end);
@@ -491,7 +491,7 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct drm_gpuva *vma)
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
-       return msm_gem_vma_map(vma, prot, msm_obj->sgt, obj->size);
+       return msm_gem_vma_map(vma, prot, msm_obj->sgt);
 }
 
 void msm_gem_unpin_locked(struct drm_gem_object *obj)
index a18872ab1393dd89d0e295d29fe09de3161df886..0e7b17b2093ba3050e3a0d1836ce0f8f6b251fe0 100644 (file)
@@ -110,9 +110,9 @@ struct msm_gem_vma {
 
 struct drm_gpuva *
 msm_gem_vma_new(struct drm_gpuvm *vm, struct drm_gem_object *obj,
-               u64 range_start, u64 range_end);
+               u64 offset, u64 range_start, u64 range_end);
 void msm_gem_vma_purge(struct drm_gpuva *vma);
-int msm_gem_vma_map(struct drm_gpuva *vma, int prot, struct sg_table *sgt, int size);
+int msm_gem_vma_map(struct drm_gpuva *vma, int prot, struct sg_table *sgt);
 void msm_gem_vma_close(struct drm_gpuva *vma);
 
 struct msm_gem_object {
index df8eb910ca31d80f3ad9f3eab01ee3d67eefeb17..ef0efd87e4a6fb0f7dab11e3ee86394f5b510a2d 100644 (file)
@@ -38,8 +38,7 @@ void msm_gem_vma_purge(struct drm_gpuva *vma)
 
 /* Map and pin vma: */
 int
-msm_gem_vma_map(struct drm_gpuva *vma, int prot,
-               struct sg_table *sgt, int size)
+msm_gem_vma_map(struct drm_gpuva *vma, int prot, struct sg_table *sgt)
 {
        struct msm_gem_vma *msm_vma = to_msm_vma(vma);
        struct msm_gem_vm *vm = to_msm_vm(vma->vm);
@@ -62,8 +61,9 @@ msm_gem_vma_map(struct drm_gpuva *vma, int prot,
         * Revisit this if we can come up with a scheme to pre-alloc pages
         * for the pgtable in map/unmap ops.
         */
-       ret = vm->mmu->funcs->map(vm->mmu, vma->va.addr, sgt, size, prot);
-
+       ret = vm->mmu->funcs->map(vm->mmu, vma->va.addr, sgt,
+                                 vma->gem.offset, vma->va.range,
+                                 prot);
        if (ret) {
                msm_vma->mapped = false;
        }
@@ -93,7 +93,7 @@ void msm_gem_vma_close(struct drm_gpuva *vma)
 /* Create a new vma and allocate an iova for it */
 struct drm_gpuva *
 msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
-               u64 range_start, u64 range_end)
+               u64 offset, u64 range_start, u64 range_end)
 {
        struct msm_gem_vm *vm = to_msm_vm(gpuvm);
        struct drm_gpuvm_bo *vm_bo;
@@ -107,6 +107,7 @@ msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
                return ERR_PTR(-ENOMEM);
 
        if (vm->managed) {
+               BUG_ON(offset != 0);
                ret = drm_mm_insert_node_in_range(&vm->mm, &vma->node,
                                                obj->size, PAGE_SIZE, 0,
                                                range_start, range_end, 0);
@@ -120,7 +121,7 @@ msm_gem_vma_new(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj,
 
        GEM_WARN_ON((range_end - range_start) > obj->size);
 
-       drm_gpuva_init(&vma->base, range_start, range_end - range_start, obj, 0);
+       drm_gpuva_init(&vma->base, range_start, range_end - range_start, obj, offset);
        vma->mapped = false;
 
        ret = drm_gpuva_insert(&vm->base, &vma->base);
index 739ce2c283a4613e74df4542ca3b68f180aa8335..3c2eb59bfd499870132d971f94059106d43b0f15 100644 (file)
@@ -113,7 +113,8 @@ static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova,
 }
 
 static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova,
-               struct sg_table *sgt, size_t len, int prot)
+                                  struct sg_table *sgt, size_t off, size_t len,
+                                  int prot)
 {
        struct msm_iommu_pagetable *pagetable = to_pagetable(mmu);
        struct io_pgtable_ops *ops = pagetable->pgtbl_ops;
@@ -125,6 +126,19 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova,
                size_t size = sg->length;
                phys_addr_t phys = sg_phys(sg);
 
+               if (!len)
+                       break;
+
+               if (size <= off) {
+                       off -= size;
+                       continue;
+               }
+
+               phys += off;
+               size -= off;
+               size = min_t(size_t, size, len);
+               off = 0;
+
                while (size) {
                        size_t pgsize, count, mapped = 0;
                        int ret;
@@ -140,6 +154,7 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova,
                        phys += mapped;
                        addr += mapped;
                        size -= mapped;
+                       len  -= mapped;
 
                        if (ret) {
                                msm_iommu_pagetable_unmap(mmu, iova, addr - iova);
@@ -388,11 +403,14 @@ static void msm_iommu_detach(struct msm_mmu *mmu)
 }
 
 static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
-               struct sg_table *sgt, size_t len, int prot)
+                        struct sg_table *sgt, size_t off, size_t len,
+                        int prot)
 {
        struct msm_iommu *iommu = to_msm_iommu(mmu);
        size_t ret;
 
+       WARN_ON(off != 0);
+
        /* The arm-smmu driver expects the addresses to be sign extended */
        if (iova & BIT_ULL(48))
                iova |= GENMASK_ULL(63, 49);
index 0c694907140d00bae86eb20411aed45650367e74..9d61999f4d42580ed2ceb196e23629c8ce32b9e9 100644 (file)
@@ -12,7 +12,7 @@
 struct msm_mmu_funcs {
        void (*detach)(struct msm_mmu *mmu);
        int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
-                       size_t len, int prot);
+                       size_t off, size_t len, int prot);
        int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
        void (*destroy)(struct msm_mmu *mmu);
        void (*set_stall)(struct msm_mmu *mmu, bool enable);