[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