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>
---
 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)
-- 
2.31.1

Reply via email to