[PATCH] drm/i915: Point the shmem backend to ttm

Adrian Larumbe adrian.larumbe at collabora.com
Thu Apr 7 03:21:44 UTC 2022


Because the core drm object filp pointer is no longer in use, retrieving it
has to be done through a specialised function. Also becase TTM is not getting
pages for a BO upon creating, they have to be retrieved before we do
an mmap from user space.

Use old shmem backend for GEN <= 5

Signed-off-by: Adrian Larumbe <adrian.larumbe at collabora.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 19 +++++-
 drivers/gpu/drm/i915/gem/i915_gem_mman.c   | 32 ++++++---
 drivers/gpu/drm/i915/gem/i915_gem_object.h |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_phys.c   | 11 +++-
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c  | 33 ++++++++--
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c    | 77 ++++++++++++++++++++--
 drivers/gpu/drm/i915/gem/i915_gem_ttm.h    |  3 +
 drivers/gpu/drm/i915/gt/shmem_utils.c      |  7 +-
 drivers/gpu/drm/i915/intel_memory_region.c |  5 +-
 9 files changed, 162 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index f5062d0c6333..01c401b9414e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -12,6 +12,7 @@
 #include <asm/smp.h>
 
 #include "gem/i915_gem_dmabuf.h"
+#include "gem/i915_gem_ttm.h"
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 #include "i915_scatterlist.h"
@@ -94,22 +95,31 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+        struct file *filp;
 	int ret;
 
+        /* This should not be a PRIME object */
+        GEM_BUG_ON(obj->base.import_attach != NULL);
+
 	if (obj->base.size < vma->vm_end - vma->vm_start)
 		return -EINVAL;
 
 	if (HAS_LMEM(i915))
 		return drm_gem_prime_mmap(&obj->base, vma);
 
-	if (!obj->base.filp)
+	if (GRAPHICS_VER(i915) > 5)
+		filp = gem_ttm_get_filep(obj);
+	else
+		filp = obj->base.filp;
+
+	if (!filp)
 		return -ENODEV;
 
-	ret = call_mmap(obj->base.filp, vma);
+	ret = call_mmap(filp, vma);
 	if (ret)
 		return ret;
 
-	vma_set_file(vma, obj->base.filp);
+	vma_set_file(vma, filp);
 
 	return 0;
 }
@@ -224,6 +234,9 @@ struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
 	exp_info.priv = gem_obj;
 	exp_info.resv = obj->base.resv;
 
+        /* This should not be a PRIME object */
+        GEM_BUG_ON(obj->base.import_attach != NULL);
+
 	if (obj->ops->dmabuf_export) {
 		int ret = obj->ops->dmabuf_export(obj);
 		if (ret)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index c3ea243d414d..c3905ed0ddd7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -64,7 +64,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_private *i915 = to_i915(dev);
 	struct drm_i915_gem_mmap *args = data;
 	struct drm_i915_gem_object *obj;
+	struct file *filp;
 	unsigned long addr;
+	int ret;
 
 	/*
 	 * mmap ioctl is disallowed for all discrete platforms,
@@ -83,12 +85,20 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
-	/* prime objects have no backing filp to GEM mmap
-	 * pages from.
-	 */
-	if (!obj->base.filp) {
-		addr = -ENXIO;
-		goto err;
+	if (obj->base.import_attach || (GRAPHICS_VER(i915) <= 5))
+		filp = obj->base.filp;
+	else {
+                ret = i915_gem_object_pin_pages_unlocked(obj);
+		if (ret) {
+			addr = ret;
+			goto err_pin;
+		}
+
+		filp = gem_ttm_get_filep(obj);
+		if (!filp) {
+			addr = -ENXIO;
+			goto err;
+		}
 	}
 
 	if (range_overflows(args->offset, args->size, (u64)obj->base.size)) {
@@ -96,7 +106,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 		goto err;
 	}
 
-	addr = vm_mmap(obj->base.filp, 0, args->size,
+	addr = vm_mmap(filp, 0, args->size,
 		       PROT_READ | PROT_WRITE, MAP_SHARED,
 		       args->offset);
 	if (IS_ERR_VALUE(addr))
@@ -111,7 +121,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 			goto err;
 		}
 		vma = find_vma(mm, addr);
-		if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
+		if (vma && __vma_matches(vma, filp, addr, args->size))
 			vma->vm_page_prot =
 				pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
 		else
@@ -122,10 +132,16 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	}
 	i915_gem_object_put(obj);
 
+        if (!obj->base.import_attach && (GRAPHICS_VER(i915) > 5))
+                i915_gem_object_unpin_pages(obj);
+
 	args->addr_ptr = (u64)addr;
 	return 0;
 
 err:
+        if (!obj->base.import_attach && (GRAPHICS_VER(i915) > 5))
+                i915_gem_object_unpin_pages(obj);
+err_pin:
 	i915_gem_object_put(obj);
 	return addr;
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 02c37fe4a535..90e1a743f9cd 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -596,7 +596,7 @@ i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
 
 int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size);
 
-bool i915_gem_object_is_shmem(const struct drm_i915_gem_object *obj);
+bool i915_gem_object_is_shmem(struct drm_i915_gem_object *obj);
 
 void __i915_gem_free_object_rcu(struct rcu_head *head);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index 0d0e46dae559..8729c30a5ac6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -11,6 +11,7 @@
 #include <drm/drm_cache.h>
 
 #include "gt/intel_gt.h"
+#include "gem/i915_gem_ttm.h"
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 #include "i915_gem_region.h"
@@ -19,7 +20,7 @@
 
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
-	struct address_space *mapping = obj->base.filp->f_mapping;
+	struct address_space *mapping;
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct scatterlist *sg;
 	struct sg_table *st;
@@ -28,6 +29,14 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	void *dst;
 	int i;
 
+        /* This should not be a PRIME object */
+        GEM_BUG_ON(obj->base.import_attach != NULL);
+
+        if (GRAPHICS_VER(i915) > 5)
+                mapping = gem_ttm_get_filep(obj)->f_mapping;
+        else
+                mapping = obj->base.filp->f_mapping;
+
 	if (GEM_WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index c2a3e388fcb4..dd8b9d59d5f8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -11,12 +11,14 @@
 #include <drm/drm_cache.h>
 
 #include "gem/i915_gem_region.h"
+#include "gem/i915_gem_ttm.h"
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 #include "i915_gem_tiling.h"
 #include "i915_gemfs.h"
 #include "i915_scatterlist.h"
 #include "i915_trace.h"
+#include "i915_gem_clflush.h"
 
 /*
  * Move pages to appropriate lru and release the pagevec, decrementing the
@@ -634,7 +636,23 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
 
 	GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU);
 
-	file = obj->base.filp;
+	if (GRAPHICS_VER(dev_priv) <= 5)
+		file = obj->base.filp;
+	else {
+		/*
+		 *  When using TTM as the main GEM backend, we need to pin the pages
+		 *  after creating the object
+		 */
+		err = i915_gem_object_pin_pages_unlocked(obj);
+		if (err) {
+			drm_dbg(&dev_priv->drm, "%s pin-pages err=%d\n", __func__, err);
+			goto fail_pin;
+		}
+
+		file = gem_ttm_get_filep(obj);
+		GEM_WARN_ON(file == NULL);
+	}
+
 	offset = 0;
 	do {
 		unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
@@ -662,9 +680,17 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
 		offset += len;
 	} while (size);
 
+        if (GRAPHICS_VER(dev_priv) > 5) {
+                i915_gem_clflush_object(obj, I915_CLFLUSH_SYNC);
+                i915_gem_object_unpin_pages(obj);
+        }
+
 	return obj;
 
 fail:
+        if (GRAPHICS_VER(dev_priv) > 5)
+                i915_gem_object_unpin_pages(obj);
+fail_pin:
 	i915_gem_object_put(obj);
 	return ERR_PTR(err);
 }
@@ -705,8 +731,3 @@ struct intel_memory_region *i915_gem_shmem_setup(struct drm_i915_private *i915,
 					  type, instance,
 					  &shmem_region_ops);
 }
-
-bool i915_gem_object_is_shmem(const struct drm_i915_gem_object *obj)
-{
-	return obj->ops == &i915_gem_shmem_ops;
-}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index e4a06fcf741a..ed16be20b895 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -20,6 +20,7 @@
 #include "gem/i915_gem_ttm.h"
 #include "gem/i915_gem_ttm_move.h"
 #include "gem/i915_gem_ttm_pm.h"
+#include "gem/i915_gem_tiling.h"
 
 #define I915_TTM_PRIO_PURGE     0
 #define I915_TTM_PRIO_NO_PAGES  1
@@ -203,6 +204,11 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
 			return PTR_ERR(filp);
 
 		mask = GFP_HIGHUSER | __GFP_RECLAIMABLE;
+                if (IS_I965GM(i915) || IS_I965G(i915)) {
+                        /* 965gm cannot relocate objects above 4GiB. */
+                        mask &= ~__GFP_HIGHMEM;
+                        mask |= __GFP_DMA32;
+                }
 
 		mapping = filp->f_mapping;
 		mapping_set_gfp_mask(mapping, mask);
@@ -768,6 +774,12 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
 		obj->mm.rsgt = rsgt;
 		__i915_gem_object_set_pages(obj, &rsgt->table,
 					    i915_sg_dma_sizes(rsgt->table.sgl));
+
+                if (i915_gem_object_needs_bit17_swizzle(obj))
+                        i915_gem_object_save_bit_17_swizzle(obj, &rsgt->table);
+
+                if (i915_gem_object_can_bypass_llc(obj))
+                        obj->cache_dirty = true;
 	}
 
 	i915_ttm_adjust_lru(obj);
@@ -1089,7 +1101,7 @@ static void i915_ttm_unmap_virtual(struct drm_i915_gem_object *obj)
 	ttm_bo_unmap_virtual(i915_gem_to_ttm(obj));
 }
 
-static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
+static const struct drm_i915_gem_object_ops i915_gem_ttm_discrete_ops = {
 	.name = "i915_gem_object_ttm",
 	.flags = I915_GEM_OBJECT_IS_SHRINKABLE |
 		 I915_GEM_OBJECT_SELF_MANAGED_SHRINK_LIST,
@@ -1108,6 +1120,20 @@ static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
 	.mmap_ops = &vm_ops_ttm,
 };
 
+static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_integrated_ops = {
+	.name = "i915_gem_object_ttm",
+	.flags = I915_GEM_OBJECT_IS_SHRINKABLE |
+		 I915_GEM_OBJECT_SELF_MANAGED_SHRINK_LIST,
+
+	.get_pages = i915_ttm_get_pages,
+	.put_pages = i915_ttm_put_pages,
+	.truncate = i915_ttm_truncate,
+	.shrink = i915_ttm_shrink,
+
+	.adjust_lru = i915_ttm_adjust_lru,
+	.delayed_free = i915_ttm_delayed_free,
+};
+
 void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
 {
 	struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
@@ -1165,7 +1191,12 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
 	int ret;
 
 	drm_gem_private_object_init(&i915->drm, &obj->base, size);
-	i915_gem_object_init(obj, &i915_gem_ttm_obj_ops, &lock_class, flags);
+
+	if (IS_DGFX(i915))
+		i915_gem_object_init(obj, &i915_gem_ttm_discrete_ops, &lock_class, flags);
+	else
+		i915_gem_object_init(obj, &i915_gem_ttm_obj_integrated_ops, &lock_class,
+				     flags);
 
 	obj->bo_offset = offset;
 
@@ -1175,8 +1206,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
 
 	INIT_RADIX_TREE(&obj->ttm.get_io_page.radix, GFP_KERNEL | __GFP_NOWARN);
 	mutex_init(&obj->ttm.get_io_page.lock);
-	bo_type = (obj->flags & I915_BO_ALLOC_USER) ? ttm_bo_type_device :
-		ttm_bo_type_kernel;
+	bo_type = (obj->ops->mmap_offset && (obj->flags & I915_BO_ALLOC_USER)) ?
+		ttm_bo_type_device : ttm_bo_type_kernel;
 
 	obj->base.vma_node.driver_private = i915_gem_to_ttm(obj);
 
@@ -1220,6 +1251,27 @@ static const struct intel_memory_region_ops ttm_system_region_ops = {
 	.release = intel_region_ttm_fini,
 };
 
+/**
+ * Return: filp.
+ */
+struct file *
+gem_ttm_get_filep(struct drm_i915_gem_object *obj)
+{
+        struct drm_device *dev = obj->base.dev;
+        struct ttm_buffer_object *bo;
+	struct i915_ttm_tt *i915_tt;
+
+	bo = i915_gem_to_ttm(obj);
+	if (!bo->ttm) {
+                drm_dbg(dev, "ttm has not been allocated for bo\n");
+		return NULL;
+	}
+
+	i915_tt = container_of(bo->ttm, typeof(*i915_tt), ttm);
+
+	return i915_tt->filp;
+}
+
 struct intel_memory_region *
 i915_gem_ttm_system_setup(struct drm_i915_private *i915,
 			  u16 type, u16 instance)
@@ -1237,3 +1289,20 @@ i915_gem_ttm_system_setup(struct drm_i915_private *i915,
 	intel_memory_region_set_name(mr, "system-ttm");
 	return mr;
 }
+
+bool i915_gem_object_is_shmem(struct drm_i915_gem_object *obj)
+{
+	struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
+
+#ifdef CONFIG_LOCKDEP
+	if (i915_gem_object_migratable(obj) &&
+	    i915_gem_object_evictable(obj))
+		assert_object_held(obj);
+#endif
+
+	/* Review list of placements to make sure object isn't migratable */
+	if (i915_gem_object_placement_possible(obj, INTEL_MEMORY_LOCAL))
+		return false;
+
+	return mr && (mr->type == INTEL_MEMORY_SYSTEM);
+}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index 73e371aa3850..cfff3b77207e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -92,4 +92,7 @@ static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem)
 	/* Once / if we support GGTT, this is also false for cached ttm_tts */
 	return mem->mem_type != I915_PL_SYSTEM;
 }
+
+struct file * gem_ttm_get_filep(struct drm_i915_gem_object *obj);
+
 #endif
diff --git a/drivers/gpu/drm/i915/gt/shmem_utils.c b/drivers/gpu/drm/i915/gt/shmem_utils.c
index 402f085f3a02..43d7fd043739 100644
--- a/drivers/gpu/drm/i915/gt/shmem_utils.c
+++ b/drivers/gpu/drm/i915/gt/shmem_utils.c
@@ -10,6 +10,8 @@
 
 #include "gem/i915_gem_object.h"
 #include "gem/i915_gem_lmem.h"
+#include "gem/i915_gem_ttm.h"
+#include "i915_drv.h"
 #include "shmem_utils.h"
 
 struct file *shmem_create_from_data(const char *name, void *data, size_t len)
@@ -32,15 +34,18 @@ struct file *shmem_create_from_data(const char *name, void *data, size_t len)
 
 struct file *shmem_create_from_object(struct drm_i915_gem_object *obj)
 {
+        struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct file *file;
 	void *ptr;
 
-	if (i915_gem_object_is_shmem(obj)) {
+        /* In case it's a PRIME buffer */
+        if (obj->base.import_attach || (GRAPHICS_VER(i915) <= 5)) {
 		file = obj->base.filp;
 		atomic_long_inc(&file->f_count);
 		return file;
 	}
 
+        /* retriving filp from ttm resource doesn't work for now, so we fall back on this */
 	ptr = i915_gem_object_pin_map_unlocked(obj, i915_gem_object_is_lmem(obj) ?
 						I915_MAP_WC : I915_MAP_WB);
 	if (IS_ERR(ptr))
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index ded78b83e0b5..3c8426a0b742 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -309,9 +309,8 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
 		instance = intel_region_map[i].instance;
 		switch (type) {
 		case INTEL_MEMORY_SYSTEM:
-			if (IS_DGFX(i915))
-				mem = i915_gem_ttm_system_setup(i915, type,
-								instance);
+			if (GRAPHICS_VER(i915) > 5)
+				mem = i915_gem_ttm_system_setup(i915, type, instance);
 			else
 				mem = i915_gem_shmem_setup(i915, type,
 							   instance);
-- 
2.35.1



More information about the Intel-gfx-trybot mailing list