[PATCH 14/18] drm/i915/ttm: mappable migration on fault
Matthew Auld
matthew.auld at intel.com
Fri Jan 14 10:37:50 UTC 2022
Signed-off-by: Matthew Auld <matthew.auld at intel.com>
---
drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 91 ++++++++++++++++++--
drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 16 ----
drivers/gpu/drm/i915/intel_region_ttm.c | 16 ++++
drivers/gpu/drm/i915/intel_region_ttm.h | 3 +
4 files changed, 104 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 3e81cf428996..c36d56b45f9d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -620,11 +620,58 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object *bo)
i915_ttm_purge(obj);
}
+static bool i915_ttm_resource_mappable(struct ttm_device *bdev,
+ struct ttm_resource *res)
+{
+ struct i915_ttm_buddy_resource *bman_res;
+ struct intel_memory_region *mr;
+ struct drm_buddy_block *block;
+ struct drm_buddy *mm;
+
+ if (!i915_ttm_cpu_maps_iomem(res))
+ return true;
+
+ /*
+ * XXX: seems slighly iffy. perhaps we should hang the io_size off the
+ * i915_ttm_buddy_manager and have a simple interface to query the
+ * io_size here.
+ */
+ mr = i915_ttm_region(bdev, res->mem_type);
+
+ if (mr->io_size == mr->total)
+ return true;
+
+ bman_res = to_ttm_buddy_resource(res);
+ mm = bman_res->mm;
+
+ /* For now range allocation also implies mappable */
+ if (bman_res->flags & DRM_BUDDY_RANGE_ALLOCATION)
+ return true;
+
+ /*
+ * This must be some kind of TOPDOWN allocation, but it might be the
+ * case that is allocated in the mappable portion, so let's check.
+ */
+ list_for_each_entry(block, &bman_res->blocks, link) {
+ u64 start = drm_buddy_block_offset(block);
+ u64 end = start + drm_buddy_block_size(mm, block);
+
+ if (start >= mr->io_size || end > mr->io_size)
+ return false;
+ }
+
+ return true;
+}
+
static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
{
+
if (!i915_ttm_cpu_maps_iomem(mem))
return 0;
+ if (!i915_ttm_resource_mappable(bdev, mem))
+ return -EINVAL;
+
mem->bus.caching = ttm_write_combined;
mem->bus.is_iomem = true;
@@ -763,14 +810,15 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
* Gem forced migration using the i915_ttm_migrate() op, is allowed even
* to regions that are not in the object's list of allowable placements.
*/
-static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
- struct intel_memory_region *mr)
+static int __i915_ttm_migrate(struct drm_i915_gem_object *obj,
+ struct intel_memory_region *mr,
+ unsigned int flags)
{
struct ttm_place requested;
struct ttm_placement placement;
int ret;
- i915_ttm_place_from_region(mr, &requested, obj->flags);
+ i915_ttm_place_from_region(mr, &requested, flags);
placement.num_placement = 1;
placement.num_busy_placement = 1;
placement.placement = &requested;
@@ -793,6 +841,12 @@ static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
return 0;
}
+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
+ struct intel_memory_region *mr)
+{
+ return __i915_ttm_migrate(obj, mr, obj->flags);
+}
+
static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
struct sg_table *st)
{
@@ -910,6 +964,10 @@ static void i915_ttm_delayed_free(struct drm_i915_gem_object *obj)
ttm_bo_put(i915_gem_to_ttm(obj));
}
+static int __i915_ttm_migrate(struct drm_i915_gem_object *obj,
+ struct intel_memory_region *mr,
+ unsigned int flags);
+
static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
{
struct vm_area_struct *area = vmf->vma;
@@ -923,9 +981,6 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
if (!obj)
return VM_FAULT_SIGBUS;
- if (obj->flags & I915_BO_ALLOC_TOPDOWN)
- return -EINVAL;
-
/* Sanity check that we allow writing into this object */
if (unlikely(i915_gem_object_is_readonly(obj) &&
area->vm_flags & VM_WRITE))
@@ -940,6 +995,30 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
}
+ if (!i915_ttm_resource_mappable(bo->bdev, bo->resource)) {
+ int err = -EINVAL;
+ int i;
+
+ for (i = 0; i < obj->mm.n_placements; i++) {
+ struct intel_memory_region *mr = obj->mm.placements[i];
+ unsigned int flags;
+
+ if (!mr->io_size && mr->type != INTEL_MEMORY_SYSTEM)
+ continue;
+
+ flags = obj->flags;
+ flags &= ~I915_BO_ALLOC_TOPDOWN;
+ err = __i915_ttm_migrate(obj, mr, flags);
+ if (!err)
+ break;
+ }
+
+ if (err) {
+ dma_resv_unlock(bo->base.resv);
+ return err;
+ }
+ }
+
if (drm_dev_enter(dev, &idx)) {
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index 1de306c03aaf..633b4351c5f3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -52,22 +52,6 @@ i915_ttm_cache_level(struct drm_i915_private *i915, struct ttm_resource *res,
I915_CACHE_NONE;
}
-static struct intel_memory_region *
-i915_ttm_region(struct ttm_device *bdev, int ttm_mem_type)
-{
- struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
-
- /* There's some room for optimization here... */
- GEM_BUG_ON(ttm_mem_type != I915_PL_SYSTEM &&
- ttm_mem_type < I915_PL_LMEM0);
- if (ttm_mem_type == I915_PL_SYSTEM)
- return intel_memory_region_lookup(i915, INTEL_MEMORY_SYSTEM,
- 0);
-
- return intel_memory_region_lookup(i915, INTEL_MEMORY_LOCAL,
- ttm_mem_type - I915_PL_LMEM0);
-}
-
/**
* i915_ttm_adjust_domains_after_move - Adjust the GEM domains after a
* TTM move
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 282802aed174..d43c4d5b312b 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -68,6 +68,22 @@ int intel_region_to_ttm_type(const struct intel_memory_region *mem)
return type;
}
+struct intel_memory_region *
+i915_ttm_region(struct ttm_device *bdev, int ttm_mem_type)
+{
+ struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
+
+ /* There's some room for optimization here... */
+ GEM_BUG_ON(ttm_mem_type != I915_PL_SYSTEM &&
+ ttm_mem_type < I915_PL_LMEM0);
+ if (ttm_mem_type == I915_PL_SYSTEM)
+ return intel_memory_region_lookup(i915, INTEL_MEMORY_SYSTEM,
+ 0);
+
+ return intel_memory_region_lookup(i915, INTEL_MEMORY_LOCAL,
+ ttm_mem_type - I915_PL_LMEM0);
+}
+
/**
* intel_region_ttm_init - Initialize a memory region for TTM.
* @mem: The region to initialize.
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h
index fdee5e7bd46c..89d8fedc61d6 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.h
+++ b/drivers/gpu/drm/i915/intel_region_ttm.h
@@ -13,6 +13,7 @@ struct drm_i915_private;
struct intel_memory_region;
struct ttm_resource;
struct ttm_device_funcs;
+struct ttm_device;
int intel_region_ttm_device_init(struct drm_i915_private *dev_priv);
@@ -30,6 +31,8 @@ void intel_region_ttm_resource_free(struct intel_memory_region *mem,
struct ttm_resource *res);
int intel_region_to_ttm_type(const struct intel_memory_region *mem);
+struct intel_memory_region *
+i915_ttm_region(struct ttm_device *bdev, int ttm_mem_type);
struct ttm_device_funcs *i915_ttm_driver(void);
--
2.31.1
More information about the Intel-gfx-trybot
mailing list