On 5/18/21 10:27 AM, Thomas Hellström wrote:
From: Maarten Lankhorst <maarten.lankho...@linux.intel.com>

Use the ttm handlers for servicing page faults, and vm_access.

Signed-off-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>

LGTM. Just need to make sure we don't forget about the caching.

Reviewed-by: Thomas Hellström <thomas.hellst...@linux.intel.com>



---
  drivers/gpu/drm/i915/gem/i915_gem_mman.c      |  17 ++-
  drivers/gpu/drm/i915/gem/i915_gem_mman.h      |   2 +
  .../gpu/drm/i915/gem/i915_gem_object_types.h  |   1 +
  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 105 +++++++++++++++++-
  4 files changed, 118 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 65db290efd16..2bf89349dde9 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -19,6 +19,7 @@
  #include "i915_gem_mman.h"
  #include "i915_trace.h"
  #include "i915_user_extensions.h"
+#include "i915_gem_ttm.h"
  #include "i915_vma.h"
static inline bool
@@ -789,7 +790,7 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void 
*data,
        return __assign_mmap_offset(file, args->handle, type, &args->offset);
  }
-static void vm_open(struct vm_area_struct *vma)
+void i915_gem_mmap_vm_open(struct vm_area_struct *vma)
  {
        struct i915_mmap_offset *mmo = vma->vm_private_data;
        struct drm_i915_gem_object *obj = mmo->obj;
@@ -798,7 +799,7 @@ static void vm_open(struct vm_area_struct *vma)
        i915_gem_object_get(obj);
  }
-static void vm_close(struct vm_area_struct *vma)
+void i915_gem_mmap_vm_close(struct vm_area_struct *vma)
  {
        struct i915_mmap_offset *mmo = vma->vm_private_data;
        struct drm_i915_gem_object *obj = mmo->obj;
@@ -810,15 +811,15 @@ static void vm_close(struct vm_area_struct *vma)
  static const struct vm_operations_struct vm_ops_gtt = {
        .fault = vm_fault_gtt,
        .access = vm_access,
-       .open = vm_open,
-       .close = vm_close,
+       .open = i915_gem_mmap_vm_open,
+       .close = i915_gem_mmap_vm_close,
  };
static const struct vm_operations_struct vm_ops_cpu = {
        .fault = vm_fault_cpu,
        .access = vm_access,
-       .open = vm_open,
-       .close = vm_close,
+       .open = i915_gem_mmap_vm_open,
+       .close = i915_gem_mmap_vm_close,
  };
static int singleton_release(struct inode *inode, struct file *file)
@@ -953,6 +954,10 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct 
*vma)
        }
        vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+ /* override ops per-object if desired */
+       if (obj->ops->mmap_ops)
+               vma->vm_ops = obj->ops->mmap_ops;
+
        return 0;
  }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.h b/drivers/gpu/drm/i915/gem/i915_gem_mman.h
index efee9e0d2508..e5bd02a6db12 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.h
@@ -28,5 +28,7 @@ void __i915_gem_object_release_mmap_gtt(struct 
drm_i915_gem_object *obj);
  void i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj);
void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj);
+void i915_gem_mmap_vm_open(struct vm_area_struct *vma);
+void i915_gem_mmap_vm_close(struct vm_area_struct *vma);
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h 
b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index b350765e1935..31d828e91cf4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -79,6 +79,7 @@ struct drm_i915_gem_object_ops {
        void (*delayed_free)(struct drm_i915_gem_object *obj);
        void (*release)(struct drm_i915_gem_object *obj);
+ const struct vm_operations_struct *mmap_ops;
        const char *name; /* friendly name for debug, e.g. lockdep classes */
  };
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 790f5ec45c4d..fe9ac50b2470 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -14,6 +14,7 @@
  #include "gem/i915_gem_region.h"
  #include "gem/i915_gem_ttm.h"
  #include "gem/i915_gem_ttm_bo_util.h"
+#include "gem/i915_gem_mman.h"
#define I915_PL_LMEM0 TTM_PL_PRIV
  #define I915_PL_SYSTEM TTM_PL_SYSTEM
@@ -345,6 +346,44 @@ static int i915_ttm_move(struct ttm_buffer_object *bo, 
bool evict,
        return 0;
  }
+static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
+{
+       if (mem->mem_type < I915_PL_LMEM0)
+               return 0;
+
+       /* We may need to revisit this later, but this allows all caching to be 
used in mmap */
+       mem->bus.caching = ttm_cached;
+       mem->bus.is_iomem = true;
+
+       return 0;
+}
+
+static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
+                                        unsigned long page_offset)
+{
+       struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+       struct sg_table *sgt = obj->ttm.cached_io_st;
+       struct scatterlist *sg;
+       unsigned int i;
+
+       GEM_WARN_ON(bo->ttm);
+
+       for_each_sgtable_dma_sg(sgt, sg, i) {
+               unsigned long sg_max = sg->length >> PAGE_SHIFT;
+
+               if (page_offset < sg_max) {
+                       unsigned long base =
+                               obj->mm.region->iomap.base - 
obj->mm.region->region.start;
+
+                       return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + 
page_offset;
+               }
+
+               page_offset -= sg_max;
+       }
+       GEM_BUG_ON(1);
+       return 0;
+}
+
  struct ttm_device_funcs i915_ttm_bo_driver = {
        .ttm_tt_create = i915_ttm_tt_create,
        .ttm_tt_unpopulate = i915_ttm_tt_unpopulate,
@@ -355,6 +394,8 @@ struct ttm_device_funcs i915_ttm_bo_driver = {
        .verify_access = NULL,
        .swap_notify = i915_ttm_swap_notify,
        .delete_mem_notify = i915_ttm_delete_mem_notify,
+       .io_mem_reserve = i915_ttm_io_mem_reserve,
+       .io_mem_pfn = i915_ttm_io_mem_pfn,
  };
static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
@@ -454,7 +495,68 @@ static void i915_ttm_delayed_free(struct 
drm_i915_gem_object *obj)
        ttm_bo_put(i915_gem_to_ttm(obj));
  }
-static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
+static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
+{
+       struct vm_area_struct *area = vmf->vma;
+       struct i915_mmap_offset *mmo = area->vm_private_data;
+       struct drm_i915_gem_object *obj = mmo->obj;
+       vm_fault_t ret;
+
+       /* Sanity check that we allow writing into this object */
+       if (unlikely(i915_gem_object_is_readonly(obj) &&
+                    area->vm_flags & VM_WRITE))
+               return VM_FAULT_SIGBUS;
+
+       ret = ttm_bo_vm_reserve(i915_gem_to_ttm(obj), vmf);
+       if (ret)
+               return ret;
+
+       ret = ttm_bo_vm_fault_reserved(i915_gem_to_ttm(obj), vmf,
+                                      drm_vma_node_start(&mmo->vma_node),
+                                      vmf->vma->vm_page_prot,
+                                      TTM_BO_VM_NUM_PREFAULT, 1);
+       if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
+               return ret;
+
+       dma_resv_unlock(obj->base.resv);
+
+       return ret;
+}
+
+static int
+vm_access_ttm(struct vm_area_struct *area, unsigned long addr,
+         void *buf, int len, int write)
+{
+       struct i915_mmap_offset *mmo = area->vm_private_data;
+       struct drm_i915_gem_object *obj = mmo->obj;
+       int err = 0;
+
+       if (i915_gem_object_is_readonly(obj) && write)
+               return -EACCES;
+
+       addr -= area->vm_start;
+       if (addr >= obj->base.size)
+               return -EINVAL;
+
+       err = i915_gem_object_lock_interruptible(obj, NULL);
+       if (err)
+               return err;
+
+       len = ttm_bo_vm_access_reserved(i915_gem_to_ttm(obj), area,
+                                       addr, buf, len, write);
+       i915_gem_object_unlock(obj);
+
+       return len;
+}
+
+static const struct vm_operations_struct vm_ops_ttm = {
+       .fault = vm_fault_ttm,
+       .access = vm_access_ttm,
+       .open = i915_gem_mmap_vm_open,
+       .close = i915_gem_mmap_vm_close,
+};
+
+const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
        .name = "i915_gem_object_ttm",
        .flags = I915_GEM_OBJECT_HAS_IOMEM,
@@ -463,6 +565,7 @@ static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
        .truncate = i915_ttm_purge,
        .adjust_lru = i915_ttm_adjust_lru,
        .delayed_free = i915_ttm_delayed_free,
+       .mmap_ops = &vm_ops_ttm,
  };
void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to