All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] drm/i915/gem: Introduce a migrate interface
@ 2021-06-28 14:46 ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

We want to be able to explicitly migrate objects between gem memory
regions, initially for display and dma-buf, but there might be more
use-cases coming up.

Introduce a gem migrate interface, add a selftest and use it for
display fb pinning and dma-buf mapping.

This series should make accelerated desktop work on DG1 with DG1-enabled
OpenGL.

v2:
- Address review comments by Matthew Auld on patch 1/5. More details on
  the patch commit message.
- Address a dma-buf locking issue pointed out by Michael Ruhl, and
  add a selftest to catch that issue moving forward.
- Rebase the dma-buf migration patch on the above-mentioned fix.

v3:
- Fix i915_gem_object_can_migrate() to return true if object is already in
  the correct region, even if the object ops doesn't have a migrate()
  callback.
- Update typo in commit message.

Matthew Auld (1):
  drm/i915/gem: Introduce a selftest for the gem object migrate
    functionality

Thomas Hellström (4):
  drm/i915/gem: Implement object migration
  drm/i915/display: Migrate objects to LMEM if possible for display
  drm/i915/gem: Fix same-driver-another-instance dma-buf export
  drm/i915/gem: Migrate to system at dma-buf map time

 drivers/gpu/drm/i915/display/intel_display.c  |   5 +-
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    |  36 ++-
 drivers/gpu/drm/i915/gem/i915_gem_domain.c    |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_lmem.c      |  21 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  97 +++++++
 drivers/gpu/drm/i915/gem/i915_gem_object.h    |  12 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |   9 +
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  69 +++--
 drivers/gpu/drm/i915/gem/i915_gem_wait.c      |  19 ++
 .../drm/i915/gem/selftests/i915_gem_dmabuf.c  |  83 +++++-
 .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 12 files changed, 546 insertions(+), 45 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c

-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 0/5] drm/i915/gem: Introduce a migrate interface
@ 2021-06-28 14:46 ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

We want to be able to explicitly migrate objects between gem memory
regions, initially for display and dma-buf, but there might be more
use-cases coming up.

Introduce a gem migrate interface, add a selftest and use it for
display fb pinning and dma-buf mapping.

This series should make accelerated desktop work on DG1 with DG1-enabled
OpenGL.

v2:
- Address review comments by Matthew Auld on patch 1/5. More details on
  the patch commit message.
- Address a dma-buf locking issue pointed out by Michael Ruhl, and
  add a selftest to catch that issue moving forward.
- Rebase the dma-buf migration patch on the above-mentioned fix.

v3:
- Fix i915_gem_object_can_migrate() to return true if object is already in
  the correct region, even if the object ops doesn't have a migrate()
  callback.
- Update typo in commit message.

Matthew Auld (1):
  drm/i915/gem: Introduce a selftest for the gem object migrate
    functionality

Thomas Hellström (4):
  drm/i915/gem: Implement object migration
  drm/i915/display: Migrate objects to LMEM if possible for display
  drm/i915/gem: Fix same-driver-another-instance dma-buf export
  drm/i915/gem: Migrate to system at dma-buf map time

 drivers/gpu/drm/i915/display/intel_display.c  |   5 +-
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    |  36 ++-
 drivers/gpu/drm/i915/gem/i915_gem_domain.c    |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_lmem.c      |  21 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  97 +++++++
 drivers/gpu/drm/i915/gem/i915_gem_object.h    |  12 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |   9 +
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  69 +++--
 drivers/gpu/drm/i915/gem/i915_gem_wait.c      |  19 ++
 .../drm/i915/gem/selftests/i915_gem_dmabuf.c  |  83 +++++-
 .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 12 files changed, 546 insertions(+), 45 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c

-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 14:46   ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel
  Cc: Thomas Hellström, matthew.auld, kernel test robot

Introduce an interface to migrate objects between regions.
This is primarily intended to migrate objects to LMEM for display and
to SYSTEM for dma-buf, but might be reused in one form or another for
performance-based migration.

v2:
- Verify that the memory region given as an id really exists.
  (Reported by Matthew Auld)
- Call i915_gem_object_{init,release}_memory_region() when switching region
  to handle also switching region lists. (Reported by Matthew Auld)
v3:
- Fix i915_gem_object_can_migrate() to return true if object is already in
  the correct region, even if the object ops doesn't have a migrate()
  callback.
- Update typo in commit message.
- Fix kerneldoc of i915_gem_object_wait_migration().

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
 drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
 5 files changed, 188 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 07e8ff9a8aae..1c18be067b58 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
 }
 
+/**
+ * i915_gem_object_can_migrate - Whether an object likely can be migrated
+ *
+ * @obj: The object to migrate
+ * @id: The region intended to migrate to
+ *
+ * Check whether the object backend supports migration to the
+ * given region. Note that pinning may affect the ability to migrate.
+ *
+ * Return: true if migration is possible, false otherwise.
+ */
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+				 enum intel_region_id id)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	unsigned int num_allowed = obj->mm.n_placements;
+	struct intel_memory_region *mr;
+	unsigned int i;
+
+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+
+	mr = i915->mm.regions[id];
+	if (!mr)
+		return false;
+
+	if (obj->mm.region == mr)
+		return true;
+
+	if (!i915_gem_object_evictable(obj))
+		return false;
+
+	if (!obj->ops->migrate)
+		return false;
+
+	if (!(obj->flags & I915_BO_ALLOC_USER))
+		return true;
+
+	if (num_allowed == 0)
+		return false;
+
+	for (i = 0; i < num_allowed; ++i) {
+		if (mr == obj->mm.placements[i])
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * i915_gem_object_migrate - Migrate an object to the desired region id
+ * @obj: The object to migrate.
+ * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
+ * not be successful in evicting other objects to make room for this object.
+ * @id: The region id to migrate to.
+ *
+ * Attempt to migrate the object to the desired memory region. The
+ * object backend must support migration and the object may not be
+ * pinned, (explicitly pinned pages or pinned vmas). The object must
+ * be locked.
+ * On successful completion, the object will have pages pointing to
+ * memory in the new region, but an async migration task may not have
+ * completed yet, and to accomplish that, i915_gem_object_wait_migration()
+ * must be called.
+ *
+ * Return: 0 on success. Negative error code on failure. In particular may
+ * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
+ * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
+ * -EBUSY if the object is pinned.
+ */
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+			    struct i915_gem_ww_ctx *ww,
+			    enum intel_region_id id)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	struct intel_memory_region *mr;
+
+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+	assert_object_held(obj);
+
+	mr = i915->mm.regions[id];
+	GEM_BUG_ON(!mr);
+
+	if (obj->mm.region == mr)
+		return 0;
+
+	if (!i915_gem_object_evictable(obj))
+		return -EBUSY;
+
+	if (!obj->ops->migrate)
+		return -EOPNOTSUPP;
+
+	return obj->ops->migrate(obj, mr);
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915)
 {
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index ea3224a480c4..8cbd7a5334e2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -17,6 +17,8 @@
 #include "i915_gem_ww.h"
 #include "i915_vma_types.h"
 
+enum intel_region_id;
+
 /*
  * XXX: There is a prevalence of the assumption that we fit the
  * object's page count inside a 32bit _signed_ variable. Let's document
@@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
 
 bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
 
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+			    struct i915_gem_ww_ctx *ww,
+			    enum intel_region_id id);
+
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+				 enum intel_region_id id);
+
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+				   unsigned int flags);
+
 #ifdef CONFIG_MMU_NOTIFIER
 static inline bool
 i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
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 441f913c87e6..ef3de2ae9723 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -18,6 +18,7 @@
 
 struct drm_i915_gem_object;
 struct intel_fronbuffer;
+struct intel_memory_region;
 
 /*
  * struct i915_lut_handle tracks the fast lookups from handle to vma used
@@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
 	 * delayed_free - Override the default delayed free implementation
 	 */
 	void (*delayed_free)(struct drm_i915_gem_object *obj);
+
+	/**
+	 * migrate - Migrate object to a different region either for
+	 * pinning or for as long as the object lock is held.
+	 */
+	int (*migrate)(struct drm_i915_gem_object *obj,
+		       struct intel_memory_region *mr);
+
 	void (*release)(struct drm_i915_gem_object *obj);
 
 	const struct vm_operations_struct *mmap_ops;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index c39d982c4fa6..8f89185b6507 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
 	return &i915_ttm_bo_driver;
 }
 
-static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
+static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
+				struct ttm_placement *placement)
 {
 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
 	struct ttm_operation_ctx ctx = {
@@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		.no_wait_gpu = false,
 	};
 	struct sg_table *st;
-	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
-	struct ttm_placement placement;
 	int real_num_busy;
 	int ret;
 
-	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
-
-	/* Move to the requested placement. */
-	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
-
 	/* First try only the requested placement. No eviction. */
-	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
-	ret = ttm_bo_validate(bo, &placement, &ctx);
+	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
+	ret = ttm_bo_validate(bo, placement, &ctx);
 	if (ret) {
 		ret = i915_ttm_err_to_gem(ret);
 		/*
@@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		 * If the initial attempt fails, allow all accepted placements,
 		 * evicting if necessary.
 		 */
-		placement.num_busy_placement = real_num_busy;
-		ret = ttm_bo_validate(bo, &placement, &ctx);
+		placement->num_busy_placement = real_num_busy;
+		ret = ttm_bo_validate(bo, placement, &ctx);
 		if (ret)
 			return i915_ttm_err_to_gem(ret);
 	}
@@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		i915_ttm_adjust_gem_after_move(obj);
 	}
 
-	/* Object either has a page vector or is an iomem object */
-	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
-	if (IS_ERR(st))
-		return PTR_ERR(st);
+	if (!obj->mm.pages) {
+		/* Object either has a page vector or is an iomem object */
+		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
+		if (IS_ERR(st))
+			return PTR_ERR(st);
 
-	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+	}
 
 	return ret;
 }
 
+static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
+{
+	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
+	struct ttm_placement placement;
+
+	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
+
+	/* Move to the requested placement. */
+	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
+
+	return __i915_ttm_get_pages(obj, &placement);
+}
+
+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
+			    struct intel_memory_region *mr)
+{
+	struct ttm_place requested;
+	struct ttm_placement placement;
+	int ret;
+
+	i915_ttm_place_from_region(mr, &requested, obj->flags);
+	placement.num_placement = 1;
+	placement.num_busy_placement = 1;
+	placement.placement = &requested;
+	placement.busy_placement = &requested;
+
+	ret = __i915_ttm_get_pages(obj, &placement);
+	if (ret)
+		return ret;
+
+	if (obj->mm.region != mr) {
+		i915_gem_object_release_memory_region(obj);
+		i915_gem_object_init_memory_region(obj, mr);
+	}
+
+	return 0;
+}
+
 static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
 			       struct sg_table *st)
 {
@@ -814,6 +848,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,
+	.migrate = i915_ttm_migrate,
 	.mmap_offset = i915_ttm_mmap_offset,
 	.mmap_ops = &vm_ops_ttm,
 };
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index 1070d3afdce7..f909aaa09d9c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	i915_gem_object_put(obj);
 	return ret;
 }
+
+/**
+ * i915_gem_object_wait_migration - Sync an accelerated migration operation
+ * @obj: The migrating object.
+ * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
+ *
+ * Wait for any pending async migration operation on the object,
+ * whether it's explicitly (i915_gem_object_migrate()) or implicitly
+ * (swapin, initial clearing) initiated.
+ *
+ * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
+ */
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+				   unsigned int flags)
+{
+	might_sleep();
+	/* NOP for now. */
+	return 0;
+}
-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 14:46   ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

Introduce an interface to migrate objects between regions.
This is primarily intended to migrate objects to LMEM for display and
to SYSTEM for dma-buf, but might be reused in one form or another for
performance-based migration.

v2:
- Verify that the memory region given as an id really exists.
  (Reported by Matthew Auld)
- Call i915_gem_object_{init,release}_memory_region() when switching region
  to handle also switching region lists. (Reported by Matthew Auld)
v3:
- Fix i915_gem_object_can_migrate() to return true if object is already in
  the correct region, even if the object ops doesn't have a migrate()
  callback.
- Update typo in commit message.
- Fix kerneldoc of i915_gem_object_wait_migration().

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
 drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
 5 files changed, 188 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 07e8ff9a8aae..1c18be067b58 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
 }
 
+/**
+ * i915_gem_object_can_migrate - Whether an object likely can be migrated
+ *
+ * @obj: The object to migrate
+ * @id: The region intended to migrate to
+ *
+ * Check whether the object backend supports migration to the
+ * given region. Note that pinning may affect the ability to migrate.
+ *
+ * Return: true if migration is possible, false otherwise.
+ */
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+				 enum intel_region_id id)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	unsigned int num_allowed = obj->mm.n_placements;
+	struct intel_memory_region *mr;
+	unsigned int i;
+
+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+
+	mr = i915->mm.regions[id];
+	if (!mr)
+		return false;
+
+	if (obj->mm.region == mr)
+		return true;
+
+	if (!i915_gem_object_evictable(obj))
+		return false;
+
+	if (!obj->ops->migrate)
+		return false;
+
+	if (!(obj->flags & I915_BO_ALLOC_USER))
+		return true;
+
+	if (num_allowed == 0)
+		return false;
+
+	for (i = 0; i < num_allowed; ++i) {
+		if (mr == obj->mm.placements[i])
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * i915_gem_object_migrate - Migrate an object to the desired region id
+ * @obj: The object to migrate.
+ * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
+ * not be successful in evicting other objects to make room for this object.
+ * @id: The region id to migrate to.
+ *
+ * Attempt to migrate the object to the desired memory region. The
+ * object backend must support migration and the object may not be
+ * pinned, (explicitly pinned pages or pinned vmas). The object must
+ * be locked.
+ * On successful completion, the object will have pages pointing to
+ * memory in the new region, but an async migration task may not have
+ * completed yet, and to accomplish that, i915_gem_object_wait_migration()
+ * must be called.
+ *
+ * Return: 0 on success. Negative error code on failure. In particular may
+ * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
+ * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
+ * -EBUSY if the object is pinned.
+ */
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+			    struct i915_gem_ww_ctx *ww,
+			    enum intel_region_id id)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	struct intel_memory_region *mr;
+
+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+	assert_object_held(obj);
+
+	mr = i915->mm.regions[id];
+	GEM_BUG_ON(!mr);
+
+	if (obj->mm.region == mr)
+		return 0;
+
+	if (!i915_gem_object_evictable(obj))
+		return -EBUSY;
+
+	if (!obj->ops->migrate)
+		return -EOPNOTSUPP;
+
+	return obj->ops->migrate(obj, mr);
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915)
 {
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index ea3224a480c4..8cbd7a5334e2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -17,6 +17,8 @@
 #include "i915_gem_ww.h"
 #include "i915_vma_types.h"
 
+enum intel_region_id;
+
 /*
  * XXX: There is a prevalence of the assumption that we fit the
  * object's page count inside a 32bit _signed_ variable. Let's document
@@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
 
 bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
 
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+			    struct i915_gem_ww_ctx *ww,
+			    enum intel_region_id id);
+
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+				 enum intel_region_id id);
+
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+				   unsigned int flags);
+
 #ifdef CONFIG_MMU_NOTIFIER
 static inline bool
 i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
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 441f913c87e6..ef3de2ae9723 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -18,6 +18,7 @@
 
 struct drm_i915_gem_object;
 struct intel_fronbuffer;
+struct intel_memory_region;
 
 /*
  * struct i915_lut_handle tracks the fast lookups from handle to vma used
@@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
 	 * delayed_free - Override the default delayed free implementation
 	 */
 	void (*delayed_free)(struct drm_i915_gem_object *obj);
+
+	/**
+	 * migrate - Migrate object to a different region either for
+	 * pinning or for as long as the object lock is held.
+	 */
+	int (*migrate)(struct drm_i915_gem_object *obj,
+		       struct intel_memory_region *mr);
+
 	void (*release)(struct drm_i915_gem_object *obj);
 
 	const struct vm_operations_struct *mmap_ops;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index c39d982c4fa6..8f89185b6507 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
 	return &i915_ttm_bo_driver;
 }
 
-static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
+static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
+				struct ttm_placement *placement)
 {
 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
 	struct ttm_operation_ctx ctx = {
@@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		.no_wait_gpu = false,
 	};
 	struct sg_table *st;
-	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
-	struct ttm_placement placement;
 	int real_num_busy;
 	int ret;
 
-	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
-
-	/* Move to the requested placement. */
-	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
-
 	/* First try only the requested placement. No eviction. */
-	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
-	ret = ttm_bo_validate(bo, &placement, &ctx);
+	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
+	ret = ttm_bo_validate(bo, placement, &ctx);
 	if (ret) {
 		ret = i915_ttm_err_to_gem(ret);
 		/*
@@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		 * If the initial attempt fails, allow all accepted placements,
 		 * evicting if necessary.
 		 */
-		placement.num_busy_placement = real_num_busy;
-		ret = ttm_bo_validate(bo, &placement, &ctx);
+		placement->num_busy_placement = real_num_busy;
+		ret = ttm_bo_validate(bo, placement, &ctx);
 		if (ret)
 			return i915_ttm_err_to_gem(ret);
 	}
@@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 		i915_ttm_adjust_gem_after_move(obj);
 	}
 
-	/* Object either has a page vector or is an iomem object */
-	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
-	if (IS_ERR(st))
-		return PTR_ERR(st);
+	if (!obj->mm.pages) {
+		/* Object either has a page vector or is an iomem object */
+		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
+		if (IS_ERR(st))
+			return PTR_ERR(st);
 
-	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+	}
 
 	return ret;
 }
 
+static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
+{
+	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
+	struct ttm_placement placement;
+
+	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
+
+	/* Move to the requested placement. */
+	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
+
+	return __i915_ttm_get_pages(obj, &placement);
+}
+
+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
+			    struct intel_memory_region *mr)
+{
+	struct ttm_place requested;
+	struct ttm_placement placement;
+	int ret;
+
+	i915_ttm_place_from_region(mr, &requested, obj->flags);
+	placement.num_placement = 1;
+	placement.num_busy_placement = 1;
+	placement.placement = &requested;
+	placement.busy_placement = &requested;
+
+	ret = __i915_ttm_get_pages(obj, &placement);
+	if (ret)
+		return ret;
+
+	if (obj->mm.region != mr) {
+		i915_gem_object_release_memory_region(obj);
+		i915_gem_object_init_memory_region(obj, mr);
+	}
+
+	return 0;
+}
+
 static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
 			       struct sg_table *st)
 {
@@ -814,6 +848,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,
+	.migrate = i915_ttm_migrate,
 	.mmap_offset = i915_ttm_mmap_offset,
 	.mmap_ops = &vm_ops_ttm,
 };
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index 1070d3afdce7..f909aaa09d9c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	i915_gem_object_put(obj);
 	return ret;
 }
+
+/**
+ * i915_gem_object_wait_migration - Sync an accelerated migration operation
+ * @obj: The migrating object.
+ * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
+ *
+ * Wait for any pending async migration operation on the object,
+ * whether it's explicitly (i915_gem_object_migrate()) or implicitly
+ * (swapin, initial clearing) initiated.
+ *
+ * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
+ */
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+				   unsigned int flags)
+{
+	might_sleep();
+	/* NOP for now. */
+	return 0;
+}
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 14:46   ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

From: Matthew Auld <matthew.auld@intel.com>

A selftest for the gem object migrate functionality. Slightly adapted
from the original by Matthew to the new interface and new fill blit
code.

Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
 .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 1c18be067b58..ff147fd59874 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs i915_gem_object_funcs = {
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/huge_gem_object.c"
 #include "selftests/huge_pages.c"
+#include "selftests/i915_gem_migrate.c"
 #include "selftests/i915_gem_object.c"
 #include "selftests/i915_gem_coherency.c"
 #endif
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
new file mode 100644
index 000000000000..a437b66f64d9
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020-2021 Intel Corporation
+ */
+
+#include "gt/intel_migrate.h"
+
+static int igt_smem_create_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	int err = 0;
+
+	/* Switch object backing-store on create */
+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	for_i915_gem_ww(&ww, err, true) {
+		err = i915_gem_object_lock(obj, &ww);
+		if (err)
+			continue;
+
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
+			err = -EINVAL;
+			continue;
+		}
+
+		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_SMEM);
+		if (err)
+			continue;
+
+		err = i915_gem_object_pin_pages(obj);
+		if (err)
+			continue;
+
+		if (i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM))
+			err = -EINVAL;
+
+		i915_gem_object_unpin_pages(obj);
+	}
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+static int igt_lmem_create_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	int err = 0;
+
+	/* Switch object backing-store on create */
+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	for_i915_gem_ww(&ww, err, true) {
+		err = i915_gem_object_lock(obj, &ww);
+		if (err)
+			continue;
+
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
+			err = -EINVAL;
+			continue;
+		}
+
+		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
+		if (err)
+			continue;
+
+		err = i915_gem_object_pin_pages(obj);
+		if (err)
+			continue;
+
+		if (i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
+			err = -EINVAL;
+
+		i915_gem_object_unpin_pages(obj);
+	}
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
+				  struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = i915_gem_object_lock(obj, ww);
+	if (err)
+		return err;
+
+	err = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_PRIORITY |
+				   I915_WAIT_ALL,
+				   MAX_SCHEDULE_TIMEOUT);
+	if (err)
+		return err;
+
+	if (i915_gem_object_is_lmem(obj)) {
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
+			pr_err("object can't migrate to smem.\n");
+			return -EINVAL;
+		}
+
+		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
+		if (err) {
+			pr_err("Object failed migration to smem\n");
+			if (err)
+				return err;
+		}
+
+		if (i915_gem_object_is_lmem(obj)) {
+			pr_err("object still backed by lmem\n");
+			err = -EINVAL;
+		}
+
+		if (!i915_gem_object_has_struct_page(obj)) {
+			pr_err("object not backed by struct page\n");
+			err = -EINVAL;
+		}
+
+	} else {
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
+			pr_err("object can't migrate to lmem.\n");
+			return -EINVAL;
+		}
+
+		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM);
+		if (err) {
+			pr_err("Object failed migration to lmem\n");
+			if (err)
+				return err;
+		}
+
+		if (i915_gem_object_has_struct_page(obj)) {
+			pr_err("object still backed by struct page\n");
+			err = -EINVAL;
+		}
+
+		if (!i915_gem_object_is_lmem(obj)) {
+			pr_err("object not backed by lmem\n");
+			err = -EINVAL;
+		}
+	}
+
+	return err;
+}
+
+static int igt_lmem_pages_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	struct i915_request *rq;
+	int err;
+	int i;
+
+	/* From LMEM to shmem and back again */
+
+	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	err = i915_gem_object_lock(obj, NULL);
+	if (err)
+		goto out_put;
+
+	err = ____i915_gem_object_get_pages(obj);
+	if (err) {
+		i915_gem_object_unlock(obj);
+		goto out_put;
+	}
+
+	err = intel_context_migrate_clear(gt->migrate.context, NULL,
+					  obj->mm.pages->sgl, obj->cache_level,
+					  i915_gem_object_is_lmem(obj),
+					  0, &rq);
+	if (rq) {
+		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
+		i915_request_put(rq);
+	}
+	i915_gem_object_unlock(obj);
+	if (err)
+		goto out_put;
+
+	for (i = 1; i <= 4; ++i) {
+		for_i915_gem_ww(&ww, err, true) {
+			err = lmem_pages_migrate_one(&ww, obj);
+			if (err)
+				continue;
+
+			err = i915_gem_object_wait_migration(obj, true);
+			if (err)
+				continue;
+
+			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
+						  obj->mm.pages->sgl,
+						  obj->cache_level,
+						  i915_gem_object_is_lmem(obj),
+						  0xdeadbeaf, &rq);
+			if (rq) {
+				dma_resv_add_excl_fence(obj->base.resv,
+							&rq->fence);
+				i915_request_put(rq);
+			}
+		}
+		if (err)
+			break;
+	}
+out_put:
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_smem_create_migrate),
+		SUBTEST(igt_lmem_create_migrate),
+		SUBTEST(igt_lmem_pages_migrate),
+	};
+
+	if (!HAS_LMEM(i915))
+		return 0;
+
+	return intel_gt_live_subtests(tests, &i915->gt);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index a68197cf1044..e2fd1b61af71 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -40,6 +40,7 @@ selftest(hugepages, i915_gem_huge_page_live_selftests)
 selftest(gem_contexts, i915_gem_context_live_selftests)
 selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
 selftest(client, i915_gem_client_blt_live_selftests)
+selftest(gem_migrate, i915_gem_migrate_live_selftests)
 selftest(reset, intel_reset_live_selftests)
 selftest(memory_region, intel_memory_region_live_selftests)
 selftest(hangcheck, intel_hangcheck_live_selftests)
-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 14:46   ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

From: Matthew Auld <matthew.auld@intel.com>

A selftest for the gem object migrate functionality. Slightly adapted
from the original by Matthew to the new interface and new fill blit
code.

Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
 .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 3 files changed, 239 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 1c18be067b58..ff147fd59874 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs i915_gem_object_funcs = {
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/huge_gem_object.c"
 #include "selftests/huge_pages.c"
+#include "selftests/i915_gem_migrate.c"
 #include "selftests/i915_gem_object.c"
 #include "selftests/i915_gem_coherency.c"
 #endif
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
new file mode 100644
index 000000000000..a437b66f64d9
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020-2021 Intel Corporation
+ */
+
+#include "gt/intel_migrate.h"
+
+static int igt_smem_create_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	int err = 0;
+
+	/* Switch object backing-store on create */
+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	for_i915_gem_ww(&ww, err, true) {
+		err = i915_gem_object_lock(obj, &ww);
+		if (err)
+			continue;
+
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
+			err = -EINVAL;
+			continue;
+		}
+
+		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_SMEM);
+		if (err)
+			continue;
+
+		err = i915_gem_object_pin_pages(obj);
+		if (err)
+			continue;
+
+		if (i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM))
+			err = -EINVAL;
+
+		i915_gem_object_unpin_pages(obj);
+	}
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+static int igt_lmem_create_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	int err = 0;
+
+	/* Switch object backing-store on create */
+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	for_i915_gem_ww(&ww, err, true) {
+		err = i915_gem_object_lock(obj, &ww);
+		if (err)
+			continue;
+
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
+			err = -EINVAL;
+			continue;
+		}
+
+		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
+		if (err)
+			continue;
+
+		err = i915_gem_object_pin_pages(obj);
+		if (err)
+			continue;
+
+		if (i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
+			err = -EINVAL;
+
+		i915_gem_object_unpin_pages(obj);
+	}
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
+				  struct drm_i915_gem_object *obj)
+{
+	int err;
+
+	err = i915_gem_object_lock(obj, ww);
+	if (err)
+		return err;
+
+	err = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_PRIORITY |
+				   I915_WAIT_ALL,
+				   MAX_SCHEDULE_TIMEOUT);
+	if (err)
+		return err;
+
+	if (i915_gem_object_is_lmem(obj)) {
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
+			pr_err("object can't migrate to smem.\n");
+			return -EINVAL;
+		}
+
+		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
+		if (err) {
+			pr_err("Object failed migration to smem\n");
+			if (err)
+				return err;
+		}
+
+		if (i915_gem_object_is_lmem(obj)) {
+			pr_err("object still backed by lmem\n");
+			err = -EINVAL;
+		}
+
+		if (!i915_gem_object_has_struct_page(obj)) {
+			pr_err("object not backed by struct page\n");
+			err = -EINVAL;
+		}
+
+	} else {
+		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
+			pr_err("object can't migrate to lmem.\n");
+			return -EINVAL;
+		}
+
+		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM);
+		if (err) {
+			pr_err("Object failed migration to lmem\n");
+			if (err)
+				return err;
+		}
+
+		if (i915_gem_object_has_struct_page(obj)) {
+			pr_err("object still backed by struct page\n");
+			err = -EINVAL;
+		}
+
+		if (!i915_gem_object_is_lmem(obj)) {
+			pr_err("object not backed by lmem\n");
+			err = -EINVAL;
+		}
+	}
+
+	return err;
+}
+
+static int igt_lmem_pages_migrate(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct drm_i915_private *i915 = gt->i915;
+	struct drm_i915_gem_object *obj;
+	struct i915_gem_ww_ctx ww;
+	struct i915_request *rq;
+	int err;
+	int i;
+
+	/* From LMEM to shmem and back again */
+
+	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	err = i915_gem_object_lock(obj, NULL);
+	if (err)
+		goto out_put;
+
+	err = ____i915_gem_object_get_pages(obj);
+	if (err) {
+		i915_gem_object_unlock(obj);
+		goto out_put;
+	}
+
+	err = intel_context_migrate_clear(gt->migrate.context, NULL,
+					  obj->mm.pages->sgl, obj->cache_level,
+					  i915_gem_object_is_lmem(obj),
+					  0, &rq);
+	if (rq) {
+		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
+		i915_request_put(rq);
+	}
+	i915_gem_object_unlock(obj);
+	if (err)
+		goto out_put;
+
+	for (i = 1; i <= 4; ++i) {
+		for_i915_gem_ww(&ww, err, true) {
+			err = lmem_pages_migrate_one(&ww, obj);
+			if (err)
+				continue;
+
+			err = i915_gem_object_wait_migration(obj, true);
+			if (err)
+				continue;
+
+			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
+						  obj->mm.pages->sgl,
+						  obj->cache_level,
+						  i915_gem_object_is_lmem(obj),
+						  0xdeadbeaf, &rq);
+			if (rq) {
+				dma_resv_add_excl_fence(obj->base.resv,
+							&rq->fence);
+				i915_request_put(rq);
+			}
+		}
+		if (err)
+			break;
+	}
+out_put:
+	i915_gem_object_put(obj);
+
+	return err;
+}
+
+int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_smem_create_migrate),
+		SUBTEST(igt_lmem_create_migrate),
+		SUBTEST(igt_lmem_pages_migrate),
+	};
+
+	if (!HAS_LMEM(i915))
+		return 0;
+
+	return intel_gt_live_subtests(tests, &i915->gt);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index a68197cf1044..e2fd1b61af71 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -40,6 +40,7 @@ selftest(hugepages, i915_gem_huge_page_live_selftests)
 selftest(gem_contexts, i915_gem_context_live_selftests)
 selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
 selftest(client, i915_gem_client_blt_live_selftests)
+selftest(gem_migrate, i915_gem_migrate_live_selftests)
 selftest(reset, intel_reset_live_selftests)
 selftest(memory_region, intel_memory_region_live_selftests)
 selftest(hangcheck, intel_hangcheck_live_selftests)
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v3 3/5] drm/i915/display: Migrate objects to LMEM if possible for display
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 14:46   ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

Objects intended to be used as display framebuffers must reside in
LMEM for discrete. If they happen to not do that, migrate them to
LMEM before pinning.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  5 ++++-
 drivers/gpu/drm/i915/gem/i915_gem_domain.c   |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_lmem.c     | 21 --------------------
 drivers/gpu/drm/i915/gem/i915_gem_object.h   |  2 --
 4 files changed, 5 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eec6c9e9cda7..026c28c612f0 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1331,6 +1331,9 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 	ret = i915_gem_object_lock(obj, &ww);
 	if (!ret && phys_cursor)
 		ret = i915_gem_object_attach_phys(obj, alignment);
+	else if (!ret && HAS_LMEM(dev_priv))
+		ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
+	/* TODO: Do we need to sync when migration becomes async? */
 	if (!ret)
 		ret = i915_gem_object_pin_pages(obj);
 	if (ret)
@@ -11778,7 +11781,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
 
 	/* object is backed with LMEM for discrete */
 	i915 = to_i915(obj->base.dev);
-	if (HAS_LMEM(i915) && !i915_gem_object_validates_to_lmem(obj)) {
+	if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
 		/* object is "remote", not in local memory */
 		i915_gem_object_put(obj);
 		return ERR_PTR(-EREMOTE);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 073822100da7..7d1400b13429 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -375,7 +375,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	struct i915_vma *vma;
 	int ret;
 
-	/* Frame buffer must be in LMEM (no migration yet) */
+	/* Frame buffer must be in LMEM */
 	if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj))
 		return ERR_PTR(-EINVAL);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
index 41d5182cd367..be1d122574af 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
@@ -23,27 +23,6 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
 	return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
 }
 
-/**
- * i915_gem_object_validates_to_lmem - Whether the object is resident in
- * lmem when pages are present.
- * @obj: The object to check.
- *
- * Migratable objects residency may change from under us if the object is
- * not pinned or locked. This function is intended to be used to check whether
- * the object can only reside in lmem when pages are present.
- *
- * Return: Whether the object is always resident in lmem when pages are
- * present.
- */
-bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj)
-{
-	struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
-
-	return !i915_gem_object_migratable(obj) &&
-		mr && (mr->type == INTEL_MEMORY_LOCAL ||
-		       mr->type == INTEL_MEMORY_STOLEN_LOCAL);
-}
-
 /**
  * i915_gem_object_is_lmem - Whether the object is resident in
  * lmem
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 8cbd7a5334e2..d423d8cac4f2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -597,8 +597,6 @@ bool i915_gem_object_evictable(struct drm_i915_gem_object *obj);
 
 bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
 
-bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
-
 int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
 			    struct i915_gem_ww_ctx *ww,
 			    enum intel_region_id id);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 3/5] drm/i915/display: Migrate objects to LMEM if possible for display
@ 2021-06-28 14:46   ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

Objects intended to be used as display framebuffers must reside in
LMEM for discrete. If they happen to not do that, migrate them to
LMEM before pinning.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  5 ++++-
 drivers/gpu/drm/i915/gem/i915_gem_domain.c   |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_lmem.c     | 21 --------------------
 drivers/gpu/drm/i915/gem/i915_gem_object.h   |  2 --
 4 files changed, 5 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eec6c9e9cda7..026c28c612f0 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1331,6 +1331,9 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 	ret = i915_gem_object_lock(obj, &ww);
 	if (!ret && phys_cursor)
 		ret = i915_gem_object_attach_phys(obj, alignment);
+	else if (!ret && HAS_LMEM(dev_priv))
+		ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
+	/* TODO: Do we need to sync when migration becomes async? */
 	if (!ret)
 		ret = i915_gem_object_pin_pages(obj);
 	if (ret)
@@ -11778,7 +11781,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
 
 	/* object is backed with LMEM for discrete */
 	i915 = to_i915(obj->base.dev);
-	if (HAS_LMEM(i915) && !i915_gem_object_validates_to_lmem(obj)) {
+	if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
 		/* object is "remote", not in local memory */
 		i915_gem_object_put(obj);
 		return ERR_PTR(-EREMOTE);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 073822100da7..7d1400b13429 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -375,7 +375,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	struct i915_vma *vma;
 	int ret;
 
-	/* Frame buffer must be in LMEM (no migration yet) */
+	/* Frame buffer must be in LMEM */
 	if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj))
 		return ERR_PTR(-EINVAL);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
index 41d5182cd367..be1d122574af 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
@@ -23,27 +23,6 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
 	return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
 }
 
-/**
- * i915_gem_object_validates_to_lmem - Whether the object is resident in
- * lmem when pages are present.
- * @obj: The object to check.
- *
- * Migratable objects residency may change from under us if the object is
- * not pinned or locked. This function is intended to be used to check whether
- * the object can only reside in lmem when pages are present.
- *
- * Return: Whether the object is always resident in lmem when pages are
- * present.
- */
-bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj)
-{
-	struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
-
-	return !i915_gem_object_migratable(obj) &&
-		mr && (mr->type == INTEL_MEMORY_LOCAL ||
-		       mr->type == INTEL_MEMORY_STOLEN_LOCAL);
-}
-
 /**
  * i915_gem_object_is_lmem - Whether the object is resident in
  * lmem
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 8cbd7a5334e2..d423d8cac4f2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -597,8 +597,6 @@ bool i915_gem_object_evictable(struct drm_i915_gem_object *obj);
 
 bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
 
-bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
-
 int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
 			    struct i915_gem_ww_ctx *ww,
 			    enum intel_region_id id);
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 14:46   ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, Ruhl, matthew.auld, Michael J

If our exported dma-bufs are imported by another instance of our driver,
that instance will typically have the imported dma-bufs locked during
map_attachment(). But the exporter also locks the same reservation
object in the map_dma_buf() callback, which leads to recursive locking.

Add a live selftest to catch this case, and as a workaround until
we fully support dynamic import and export, declare the exporter dynamic
by providing NOP pin() and unpin() functions. This means our map_dma_buf()
callback will *always* get called locked, and by pinning unconditionally
in i915_gem_map_dma_buf() we make sure we don't need to use the
move_notify() functionality which is not yet implemented.

Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
 .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81 ++++++++++++++++++-
 2 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 616c3a2f1baf..1d1eeb167d28 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -12,6 +12,8 @@
 #include "i915_gem_object.h"
 #include "i915_scatterlist.h"
 
+I915_SELFTEST_DECLARE(static bool force_different_devices;)
+
 static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
 {
 	return to_intel_bo(buf->priv);
@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 	struct scatterlist *src, *dst;
 	int ret, i;
 
-	ret = i915_gem_object_pin_pages_unlocked(obj);
+	assert_object_held(obj);
+
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direct
 	return err;
 }
 
+/*
+ * As a workaround until we fully support dynamic import and export,
+ * declare the exporter dynamic by providing NOP pin() and unpin() functions.
+ * This means our i915_gem_map_dma_buf() callback will *always* get called
+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we make
+ * sure we don't need to use the move_notify() functionality which is
+ * not yet implemented. Typically for the same-driver-another-instance case,
+ * i915_gem_map_dma_buf() will be called at importer attach time and the
+ * mapped sg_list will be cached by the dma-buf core for the
+ * duration of the attachment.
+ */
+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
+{
+	return 0;
+}
+
+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
+{
+}
+
 static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.map_dma_buf = i915_gem_map_dma_buf,
 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.vunmap = i915_gem_dmabuf_vunmap,
 	.begin_cpu_access = i915_gem_begin_cpu_access,
 	.end_cpu_access = i915_gem_end_cpu_access,
+	.pin = i915_gem_dmabuf_pin,
+	.unpin = i915_gem_dmabuf_unpin,
 };
 
 struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
@@ -241,7 +267,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 	if (dma_buf->ops == &i915_dmabuf_ops) {
 		obj = dma_buf_to_obj(dma_buf);
 		/* is it from our device? */
-		if (obj->base.dev == dev) {
+		if (obj->base.dev == dev &&
+		    !I915_SELFTEST_ONLY(force_different_devices)) {
 			/*
 			 * Importing dmabuf exported from out own gem increases
 			 * refcount on gem itself instead of f_count of dmabuf.
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index dd74bc09ec88..24735d6c12a2 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
 static int igt_dmabuf_import_self(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj, *import_obj;
 	struct drm_gem_object *import;
 	struct dma_buf *dmabuf;
 	int err;
@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
 		err = -EINVAL;
 		goto out_import;
 	}
+	import_obj = to_intel_bo(import);
+
+	i915_gem_object_lock(import_obj, NULL);
+	err = ____i915_gem_object_get_pages(import_obj);
+	i915_gem_object_unlock(import_obj);
+	if (err) {
+		pr_err("Same object dma-buf get_pages failed!\n");
+		goto out_import;
+	}
 
 	err = 0;
 out_import:
-	i915_gem_object_put(to_intel_bo(import));
+	i915_gem_object_put(import_obj);
+out_dmabuf:
+	dma_buf_put(dmabuf);
+out:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+static int igt_dmabuf_import_same_driver(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj, *import_obj;
+	struct drm_gem_object *import;
+	struct dma_buf *dmabuf;
+	int err;
+
+	force_different_devices = true;
+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		goto out_ret;
+
+	dmabuf = i915_gem_prime_export(&obj->base, 0);
+	if (IS_ERR(dmabuf)) {
+		pr_err("i915_gem_prime_export failed with err=%d\n",
+		       (int)PTR_ERR(dmabuf));
+		err = PTR_ERR(dmabuf);
+		goto out;
+	}
+
+	import = i915_gem_prime_import(&i915->drm, dmabuf);
+	if (IS_ERR(import)) {
+		pr_err("i915_gem_prime_import failed with err=%d\n",
+		       (int)PTR_ERR(import));
+		err = PTR_ERR(import);
+		goto out_dmabuf;
+	}
+
+	if (import == &obj->base) {
+		pr_err("i915_gem_prime_import reused gem object!\n");
+		err = -EINVAL;
+		goto out_import;
+	}
+
+	import_obj = to_intel_bo(import);
+
+	i915_gem_object_lock(import_obj, NULL);
+	err = ____i915_gem_object_get_pages(import_obj);
+	if (err) {
+		pr_err("Different objects dma-buf get_pages failed!\n");
+		i915_gem_object_unlock(import_obj);
+		goto out_import;
+	}
+
+	/*
+	 * If the exported object is not in system memory, something
+	 * weird is going on. TODO: When p2p is supported, this is no
+	 * longer considered weird.
+	 */
+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
+		pr_err("Exported dma-buf is not in system memory\n");
+		err = -EINVAL;
+	}
+	i915_gem_object_unlock(import_obj);
+
+out_import:
+	i915_gem_object_put(import_obj);
 out_dmabuf:
 	dma_buf_put(dmabuf);
 out:
 	i915_gem_object_put(obj);
+out_ret:
+	force_different_devices = false;
 	return err;
 }
 
@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_dmabuf_export),
+		SUBTEST(igt_dmabuf_import_same_driver),
 	};
 
 	return i915_subtests(tests, i915);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
@ 2021-06-28 14:46   ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, Ruhl, matthew.auld

If our exported dma-bufs are imported by another instance of our driver,
that instance will typically have the imported dma-bufs locked during
map_attachment(). But the exporter also locks the same reservation
object in the map_dma_buf() callback, which leads to recursive locking.

Add a live selftest to catch this case, and as a workaround until
we fully support dynamic import and export, declare the exporter dynamic
by providing NOP pin() and unpin() functions. This means our map_dma_buf()
callback will *always* get called locked, and by pinning unconditionally
in i915_gem_map_dma_buf() we make sure we don't need to use the
move_notify() functionality which is not yet implemented.

Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
 .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81 ++++++++++++++++++-
 2 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 616c3a2f1baf..1d1eeb167d28 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -12,6 +12,8 @@
 #include "i915_gem_object.h"
 #include "i915_scatterlist.h"
 
+I915_SELFTEST_DECLARE(static bool force_different_devices;)
+
 static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
 {
 	return to_intel_bo(buf->priv);
@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 	struct scatterlist *src, *dst;
 	int ret, i;
 
-	ret = i915_gem_object_pin_pages_unlocked(obj);
+	assert_object_held(obj);
+
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direct
 	return err;
 }
 
+/*
+ * As a workaround until we fully support dynamic import and export,
+ * declare the exporter dynamic by providing NOP pin() and unpin() functions.
+ * This means our i915_gem_map_dma_buf() callback will *always* get called
+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we make
+ * sure we don't need to use the move_notify() functionality which is
+ * not yet implemented. Typically for the same-driver-another-instance case,
+ * i915_gem_map_dma_buf() will be called at importer attach time and the
+ * mapped sg_list will be cached by the dma-buf core for the
+ * duration of the attachment.
+ */
+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
+{
+	return 0;
+}
+
+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
+{
+}
+
 static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.map_dma_buf = i915_gem_map_dma_buf,
 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.vunmap = i915_gem_dmabuf_vunmap,
 	.begin_cpu_access = i915_gem_begin_cpu_access,
 	.end_cpu_access = i915_gem_end_cpu_access,
+	.pin = i915_gem_dmabuf_pin,
+	.unpin = i915_gem_dmabuf_unpin,
 };
 
 struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
@@ -241,7 +267,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 	if (dma_buf->ops == &i915_dmabuf_ops) {
 		obj = dma_buf_to_obj(dma_buf);
 		/* is it from our device? */
-		if (obj->base.dev == dev) {
+		if (obj->base.dev == dev &&
+		    !I915_SELFTEST_ONLY(force_different_devices)) {
 			/*
 			 * Importing dmabuf exported from out own gem increases
 			 * refcount on gem itself instead of f_count of dmabuf.
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index dd74bc09ec88..24735d6c12a2 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
 static int igt_dmabuf_import_self(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj, *import_obj;
 	struct drm_gem_object *import;
 	struct dma_buf *dmabuf;
 	int err;
@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
 		err = -EINVAL;
 		goto out_import;
 	}
+	import_obj = to_intel_bo(import);
+
+	i915_gem_object_lock(import_obj, NULL);
+	err = ____i915_gem_object_get_pages(import_obj);
+	i915_gem_object_unlock(import_obj);
+	if (err) {
+		pr_err("Same object dma-buf get_pages failed!\n");
+		goto out_import;
+	}
 
 	err = 0;
 out_import:
-	i915_gem_object_put(to_intel_bo(import));
+	i915_gem_object_put(import_obj);
+out_dmabuf:
+	dma_buf_put(dmabuf);
+out:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+static int igt_dmabuf_import_same_driver(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj, *import_obj;
+	struct drm_gem_object *import;
+	struct dma_buf *dmabuf;
+	int err;
+
+	force_different_devices = true;
+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		goto out_ret;
+
+	dmabuf = i915_gem_prime_export(&obj->base, 0);
+	if (IS_ERR(dmabuf)) {
+		pr_err("i915_gem_prime_export failed with err=%d\n",
+		       (int)PTR_ERR(dmabuf));
+		err = PTR_ERR(dmabuf);
+		goto out;
+	}
+
+	import = i915_gem_prime_import(&i915->drm, dmabuf);
+	if (IS_ERR(import)) {
+		pr_err("i915_gem_prime_import failed with err=%d\n",
+		       (int)PTR_ERR(import));
+		err = PTR_ERR(import);
+		goto out_dmabuf;
+	}
+
+	if (import == &obj->base) {
+		pr_err("i915_gem_prime_import reused gem object!\n");
+		err = -EINVAL;
+		goto out_import;
+	}
+
+	import_obj = to_intel_bo(import);
+
+	i915_gem_object_lock(import_obj, NULL);
+	err = ____i915_gem_object_get_pages(import_obj);
+	if (err) {
+		pr_err("Different objects dma-buf get_pages failed!\n");
+		i915_gem_object_unlock(import_obj);
+		goto out_import;
+	}
+
+	/*
+	 * If the exported object is not in system memory, something
+	 * weird is going on. TODO: When p2p is supported, this is no
+	 * longer considered weird.
+	 */
+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
+		pr_err("Exported dma-buf is not in system memory\n");
+		err = -EINVAL;
+	}
+	i915_gem_object_unlock(import_obj);
+
+out_import:
+	i915_gem_object_put(import_obj);
 out_dmabuf:
 	dma_buf_put(dmabuf);
 out:
 	i915_gem_object_put(obj);
+out_ret:
+	force_different_devices = false;
 	return err;
 }
 
@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_dmabuf_export),
+		SUBTEST(igt_dmabuf_import_same_driver),
 	};
 
 	return i915_subtests(tests, i915);
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 14:46   ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

Until we support p2p dma or as a complement to that, migrate data
to system memory at dma-buf map time if possible.

v2:
- Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
  selftest to migrate if we are LMEM capable.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
 drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 1d1eeb167d28..5207aa3af009 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 
 	assert_object_held(obj);
 
-	ret = i915_gem_object_pin_pages(obj);
+	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
+		return ERR_PTR(-EOPNOTSUPP);
+
+	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
+	if (!ret)
+		ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index 24735d6c12a2..b6278dba98d0 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -94,7 +94,9 @@ static int igt_dmabuf_import_same_driver(void *arg)
 	int err;
 
 	force_different_devices = true;
-	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
+	if (IS_ERR(obj))
+		obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
 	if (IS_ERR(obj))
 		goto out_ret;
 
-- 
2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
@ 2021-06-28 14:46   ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 14:46 UTC (permalink / raw)
  To: intel-gfx, dri-devel; +Cc: Thomas Hellström, matthew.auld

Until we support p2p dma or as a complement to that, migrate data
to system memory at dma-buf map time if possible.

v2:
- Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
  selftest to migrate if we are LMEM capable.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
 drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 1d1eeb167d28..5207aa3af009 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 
 	assert_object_held(obj);
 
-	ret = i915_gem_object_pin_pages(obj);
+	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
+		return ERR_PTR(-EOPNOTSUPP);
+
+	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
+	if (!ret)
+		ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index 24735d6c12a2..b6278dba98d0 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -94,7 +94,9 @@ static int igt_dmabuf_import_same_driver(void *arg)
 	int err;
 
 	force_different_devices = true;
-	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
+	if (IS_ERR(obj))
+		obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
 	if (IS_ERR(obj))
 		goto out_ret;
 
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 3/5] drm/i915/display: Migrate objects to LMEM if possible for display
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 15:20     ` Matthew Auld
  -1 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 15:20 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel

On 28/06/2021 15:46, Thomas Hellström wrote:
> Objects intended to be used as display framebuffers must reside in
> LMEM for discrete. If they happen to not do that, migrate them to
> LMEM before pinning.
> 
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Looks reasonable to me,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 3/5] drm/i915/display: Migrate objects to LMEM if possible for display
@ 2021-06-28 15:20     ` Matthew Auld
  0 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 15:20 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel

On 28/06/2021 15:46, Thomas Hellström wrote:
> Objects intended to be used as display framebuffers must reside in
> LMEM for discrete. If they happen to not do that, migrate them to
> LMEM before pinning.
> 
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Looks reasonable to me,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 15:51     ` Matthew Auld
  -1 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 15:51 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel

On 28/06/2021 15:46, Thomas Hellström wrote:
> From: Matthew Auld <matthew.auld@intel.com>
> 
> A selftest for the gem object migrate functionality. Slightly adapted
> from the original by Matthew to the new interface and new fill blit
> code.
> 
> Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>   .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
>   .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>   3 files changed, 239 insertions(+)
>   create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 1c18be067b58..ff147fd59874 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs i915_gem_object_funcs = {
>   #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>   #include "selftests/huge_gem_object.c"
>   #include "selftests/huge_pages.c"
> +#include "selftests/i915_gem_migrate.c"
>   #include "selftests/i915_gem_object.c"
>   #include "selftests/i915_gem_coherency.c"
>   #endif
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> new file mode 100644
> index 000000000000..a437b66f64d9
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> @@ -0,0 +1,237 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020-2021 Intel Corporation
> + */
> +
> +#include "gt/intel_migrate.h"
> +
> +static int igt_smem_create_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	int err = 0;
> +
> +	/* Switch object backing-store on create */
> +	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	for_i915_gem_ww(&ww, err, true) {
> +		err = i915_gem_object_lock(obj, &ww);
> +		if (err)
> +			continue;
> +
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
> +			err = -EINVAL;
> +			continue;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_SMEM);
> +		if (err)
> +			continue;
> +
> +		err = i915_gem_object_pin_pages(obj);
> +		if (err)
> +			continue;
> +
> +		if (i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM))
> +			err = -EINVAL;
> +
> +		i915_gem_object_unpin_pages(obj);
> +	}
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +static int igt_lmem_create_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	int err = 0;
> +
> +	/* Switch object backing-store on create */
> +	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	for_i915_gem_ww(&ww, err, true) {
> +		err = i915_gem_object_lock(obj, &ww);
> +		if (err)
> +			continue;
> +
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
> +			err = -EINVAL;
> +			continue;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
> +		if (err)
> +			continue;
> +
> +		err = i915_gem_object_pin_pages(obj);
> +		if (err)
> +			continue;
> +
> +		if (i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
> +			err = -EINVAL;
> +
> +		i915_gem_object_unpin_pages(obj);
> +	}
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
> +				  struct drm_i915_gem_object *obj)
> +{
> +	int err;
> +
> +	err = i915_gem_object_lock(obj, ww);
> +	if (err)
> +		return err;
> +
> +	err = i915_gem_object_wait(obj,
> +				   I915_WAIT_INTERRUPTIBLE |
> +				   I915_WAIT_PRIORITY |
> +				   I915_WAIT_ALL,
> +				   MAX_SCHEDULE_TIMEOUT);
> +	if (err)
> +		return err;
> +
> +	if (i915_gem_object_is_lmem(obj)) {
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
> +			pr_err("object can't migrate to smem.\n");
> +			return -EINVAL;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
> +		if (err) {
> +			pr_err("Object failed migration to smem\n");
> +			if (err)
> +				return err;
> +		}
> +
> +		if (i915_gem_object_is_lmem(obj)) {
> +			pr_err("object still backed by lmem\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (!i915_gem_object_has_struct_page(obj)) {
> +			pr_err("object not backed by struct page\n");
> +			err = -EINVAL;
> +		}
> +
> +	} else {
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
> +			pr_err("object can't migrate to lmem.\n");
> +			return -EINVAL;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM);
> +		if (err) {
> +			pr_err("Object failed migration to lmem\n");
> +			if (err)
> +				return err;
> +		}
> +
> +		if (i915_gem_object_has_struct_page(obj)) {
> +			pr_err("object still backed by struct page\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (!i915_gem_object_is_lmem(obj)) {
> +			pr_err("object not backed by lmem\n");
> +			err = -EINVAL;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static int igt_lmem_pages_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	struct i915_request *rq;
> +	int err;
> +	int i;
> +
> +	/* From LMEM to shmem and back again */
> +
> +	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	err = i915_gem_object_lock(obj, NULL);
> +	if (err)
> +		goto out_put;
> +
> +	err = ____i915_gem_object_get_pages(obj);
> +	if (err) {
> +		i915_gem_object_unlock(obj);
> +		goto out_put;
> +	}
> +
> +	err = intel_context_migrate_clear(gt->migrate.context, NULL,
> +					  obj->mm.pages->sgl, obj->cache_level,
> +					  i915_gem_object_is_lmem(obj),
> +					  0, &rq);
> +	if (rq) {
> +		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
> +		i915_request_put(rq);
> +	}
> +	i915_gem_object_unlock(obj);
> +	if (err)
> +		goto out_put;
> +
> +	for (i = 1; i <= 4; ++i) {
> +		for_i915_gem_ww(&ww, err, true) {
> +			err = lmem_pages_migrate_one(&ww, obj);
> +			if (err)
> +				continue;
> +
> +			err = i915_gem_object_wait_migration(obj, true);
> +			if (err)
> +				continue;
> +
> +			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
> +						  obj->mm.pages->sgl,
> +						  obj->cache_level,
> +						  i915_gem_object_is_lmem(obj),
> +						  0xdeadbeaf, &rq);
> +			if (rq) {
> +				dma_resv_add_excl_fence(obj->base.resv,
> +							&rq->fence);
> +				i915_request_put(rq);
> +			}
> +		}
> +		if (err)
> +			break;
> +	}
> +out_put:
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
> +{
> +	static const struct i915_subtest tests[] = {
> +		SUBTEST(igt_smem_create_migrate),
> +		SUBTEST(igt_lmem_create_migrate),
> +		SUBTEST(igt_lmem_pages_migrate),

Might be good to dirty the pages before the migration, and then verify 
they still match at the end?

> +	};
> +
> +	if (!HAS_LMEM(i915))
> +		return 0;
> +
> +	return intel_gt_live_subtests(tests, &i915->gt);
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> index a68197cf1044..e2fd1b61af71 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -40,6 +40,7 @@ selftest(hugepages, i915_gem_huge_page_live_selftests)
>   selftest(gem_contexts, i915_gem_context_live_selftests)
>   selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
>   selftest(client, i915_gem_client_blt_live_selftests)
> +selftest(gem_migrate, i915_gem_migrate_live_selftests)
>   selftest(reset, intel_reset_live_selftests)
>   selftest(memory_region, intel_memory_region_live_selftests)
>   selftest(hangcheck, intel_hangcheck_live_selftests)
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 15:51     ` Matthew Auld
  0 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 15:51 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel

On 28/06/2021 15:46, Thomas Hellström wrote:
> From: Matthew Auld <matthew.auld@intel.com>
> 
> A selftest for the gem object migrate functionality. Slightly adapted
> from the original by Matthew to the new interface and new fill blit
> code.
> 
> Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>   .../drm/i915/gem/selftests/i915_gem_migrate.c | 237 ++++++++++++++++++
>   .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>   3 files changed, 239 insertions(+)
>   create mode 100644 drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 1c18be067b58..ff147fd59874 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs i915_gem_object_funcs = {
>   #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>   #include "selftests/huge_gem_object.c"
>   #include "selftests/huge_pages.c"
> +#include "selftests/i915_gem_migrate.c"
>   #include "selftests/i915_gem_object.c"
>   #include "selftests/i915_gem_coherency.c"
>   #endif
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> new file mode 100644
> index 000000000000..a437b66f64d9
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> @@ -0,0 +1,237 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020-2021 Intel Corporation
> + */
> +
> +#include "gt/intel_migrate.h"
> +
> +static int igt_smem_create_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	int err = 0;
> +
> +	/* Switch object backing-store on create */
> +	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	for_i915_gem_ww(&ww, err, true) {
> +		err = i915_gem_object_lock(obj, &ww);
> +		if (err)
> +			continue;
> +
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
> +			err = -EINVAL;
> +			continue;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_SMEM);
> +		if (err)
> +			continue;
> +
> +		err = i915_gem_object_pin_pages(obj);
> +		if (err)
> +			continue;
> +
> +		if (i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM))
> +			err = -EINVAL;
> +
> +		i915_gem_object_unpin_pages(obj);
> +	}
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +static int igt_lmem_create_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	int err = 0;
> +
> +	/* Switch object backing-store on create */
> +	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	for_i915_gem_ww(&ww, err, true) {
> +		err = i915_gem_object_lock(obj, &ww);
> +		if (err)
> +			continue;
> +
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
> +			err = -EINVAL;
> +			continue;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
> +		if (err)
> +			continue;
> +
> +		err = i915_gem_object_pin_pages(obj);
> +		if (err)
> +			continue;
> +
> +		if (i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
> +			err = -EINVAL;
> +
> +		i915_gem_object_unpin_pages(obj);
> +	}
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
> +				  struct drm_i915_gem_object *obj)
> +{
> +	int err;
> +
> +	err = i915_gem_object_lock(obj, ww);
> +	if (err)
> +		return err;
> +
> +	err = i915_gem_object_wait(obj,
> +				   I915_WAIT_INTERRUPTIBLE |
> +				   I915_WAIT_PRIORITY |
> +				   I915_WAIT_ALL,
> +				   MAX_SCHEDULE_TIMEOUT);
> +	if (err)
> +		return err;
> +
> +	if (i915_gem_object_is_lmem(obj)) {
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM)) {
> +			pr_err("object can't migrate to smem.\n");
> +			return -EINVAL;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
> +		if (err) {
> +			pr_err("Object failed migration to smem\n");
> +			if (err)
> +				return err;
> +		}
> +
> +		if (i915_gem_object_is_lmem(obj)) {
> +			pr_err("object still backed by lmem\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (!i915_gem_object_has_struct_page(obj)) {
> +			pr_err("object not backed by struct page\n");
> +			err = -EINVAL;
> +		}
> +
> +	} else {
> +		if (!i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
> +			pr_err("object can't migrate to lmem.\n");
> +			return -EINVAL;
> +		}
> +
> +		err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM);
> +		if (err) {
> +			pr_err("Object failed migration to lmem\n");
> +			if (err)
> +				return err;
> +		}
> +
> +		if (i915_gem_object_has_struct_page(obj)) {
> +			pr_err("object still backed by struct page\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (!i915_gem_object_is_lmem(obj)) {
> +			pr_err("object not backed by lmem\n");
> +			err = -EINVAL;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static int igt_lmem_pages_migrate(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct drm_i915_private *i915 = gt->i915;
> +	struct drm_i915_gem_object *obj;
> +	struct i915_gem_ww_ctx ww;
> +	struct i915_request *rq;
> +	int err;
> +	int i;
> +
> +	/* From LMEM to shmem and back again */
> +
> +	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
> +	if (IS_ERR(obj))
> +		return PTR_ERR(obj);
> +
> +	err = i915_gem_object_lock(obj, NULL);
> +	if (err)
> +		goto out_put;
> +
> +	err = ____i915_gem_object_get_pages(obj);
> +	if (err) {
> +		i915_gem_object_unlock(obj);
> +		goto out_put;
> +	}
> +
> +	err = intel_context_migrate_clear(gt->migrate.context, NULL,
> +					  obj->mm.pages->sgl, obj->cache_level,
> +					  i915_gem_object_is_lmem(obj),
> +					  0, &rq);
> +	if (rq) {
> +		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
> +		i915_request_put(rq);
> +	}
> +	i915_gem_object_unlock(obj);
> +	if (err)
> +		goto out_put;
> +
> +	for (i = 1; i <= 4; ++i) {
> +		for_i915_gem_ww(&ww, err, true) {
> +			err = lmem_pages_migrate_one(&ww, obj);
> +			if (err)
> +				continue;
> +
> +			err = i915_gem_object_wait_migration(obj, true);
> +			if (err)
> +				continue;
> +
> +			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
> +						  obj->mm.pages->sgl,
> +						  obj->cache_level,
> +						  i915_gem_object_is_lmem(obj),
> +						  0xdeadbeaf, &rq);
> +			if (rq) {
> +				dma_resv_add_excl_fence(obj->base.resv,
> +							&rq->fence);
> +				i915_request_put(rq);
> +			}
> +		}
> +		if (err)
> +			break;
> +	}
> +out_put:
> +	i915_gem_object_put(obj);
> +
> +	return err;
> +}
> +
> +int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
> +{
> +	static const struct i915_subtest tests[] = {
> +		SUBTEST(igt_smem_create_migrate),
> +		SUBTEST(igt_lmem_create_migrate),
> +		SUBTEST(igt_lmem_pages_migrate),

Might be good to dirty the pages before the migration, and then verify 
they still match at the end?

> +	};
> +
> +	if (!HAS_LMEM(i915))
> +		return 0;
> +
> +	return intel_gt_live_subtests(tests, &i915->gt);
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> index a68197cf1044..e2fd1b61af71 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -40,6 +40,7 @@ selftest(hugepages, i915_gem_huge_page_live_selftests)
>   selftest(gem_contexts, i915_gem_context_live_selftests)
>   selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
>   selftest(client, i915_gem_client_blt_live_selftests)
> +selftest(gem_migrate, i915_gem_migrate_live_selftests)
>   selftest(reset, intel_reset_live_selftests)
>   selftest(memory_region, intel_memory_region_live_selftests)
>   selftest(hangcheck, intel_hangcheck_live_selftests)
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 16:28     ` Matthew Auld
  -1 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 16:28 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: kernel test robot

On 28/06/2021 15:46, Thomas Hellström wrote:
> Introduce an interface to migrate objects between regions.
> This is primarily intended to migrate objects to LMEM for display and
> to SYSTEM for dma-buf, but might be reused in one form or another for
> performance-based migration.
> 
> v2:
> - Verify that the memory region given as an id really exists.
>    (Reported by Matthew Auld)
> - Call i915_gem_object_{init,release}_memory_region() when switching region
>    to handle also switching region lists. (Reported by Matthew Auld)
> v3:
> - Fix i915_gem_object_can_migrate() to return true if object is already in
>    the correct region, even if the object ops doesn't have a migrate()
>    callback.
> - Update typo in commit message.
> - Fix kerneldoc of i915_gem_object_wait_migration().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>   .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>   drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>   5 files changed, 188 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 07e8ff9a8aae..1c18be067b58 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
>   	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>   }
>   
> +/**
> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
> + *
> + * @obj: The object to migrate
> + * @id: The region intended to migrate to
> + *
> + * Check whether the object backend supports migration to the
> + * given region. Note that pinning may affect the ability to migrate.
> + *
> + * Return: true if migration is possible, false otherwise.
> + */
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	unsigned int num_allowed = obj->mm.n_placements;
> +	struct intel_memory_region *mr;
> +	unsigned int i;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +
> +	mr = i915->mm.regions[id];
> +	if (!mr)
> +		return false;
> +
> +	if (obj->mm.region == mr)
> +		return true;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return false;
> +
> +	if (!obj->ops->migrate)
> +		return false;
> +
> +	if (!(obj->flags & I915_BO_ALLOC_USER))
> +		return true;
> +
> +	if (num_allowed == 0)
> +		return false;
> +
> +	for (i = 0; i < num_allowed; ++i) {
> +		if (mr == obj->mm.placements[i])
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * i915_gem_object_migrate - Migrate an object to the desired region id
> + * @obj: The object to migrate.
> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
> + * not be successful in evicting other objects to make room for this object.
> + * @id: The region id to migrate to.
> + *
> + * Attempt to migrate the object to the desired memory region. The
> + * object backend must support migration and the object may not be
> + * pinned, (explicitly pinned pages or pinned vmas). The object must
> + * be locked.
> + * On successful completion, the object will have pages pointing to
> + * memory in the new region, but an async migration task may not have
> + * completed yet, and to accomplish that, i915_gem_object_wait_migration()
> + * must be called.
> + *
> + * Return: 0 on success. Negative error code on failure. In particular may
> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
> + * -EBUSY if the object is pinned.
> + */
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	struct intel_memory_region *mr;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +	assert_object_held(obj);
> +
> +	mr = i915->mm.regions[id];
> +	GEM_BUG_ON(!mr);
> +
> +	if (obj->mm.region == mr)
> +		return 0;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return -EBUSY;
> +
> +	if (!obj->ops->migrate)
> +		return -EOPNOTSUPP;
> +
> +	return obj->ops->migrate(obj, mr);
> +}
> +
>   void i915_gem_init__objects(struct drm_i915_private *i915)
>   {
>   	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index ea3224a480c4..8cbd7a5334e2 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -17,6 +17,8 @@
>   #include "i915_gem_ww.h"
>   #include "i915_vma_types.h"
>   
> +enum intel_region_id;
> +
>   /*
>    * XXX: There is a prevalence of the assumption that we fit the
>    * object's page count inside a 32bit _signed_ variable. Let's document
> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
>   
>   bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
>   
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id);
> +
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id);
> +
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags);
> +
>   #ifdef CONFIG_MMU_NOTIFIER
>   static inline bool
>   i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
> 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 441f913c87e6..ef3de2ae9723 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> @@ -18,6 +18,7 @@
>   
>   struct drm_i915_gem_object;
>   struct intel_fronbuffer;
> +struct intel_memory_region;
>   
>   /*
>    * struct i915_lut_handle tracks the fast lookups from handle to vma used
> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>   	 * delayed_free - Override the default delayed free implementation
>   	 */
>   	void (*delayed_free)(struct drm_i915_gem_object *obj);
> +
> +	/**
> +	 * migrate - Migrate object to a different region either for
> +	 * pinning or for as long as the object lock is held.
> +	 */
> +	int (*migrate)(struct drm_i915_gem_object *obj,
> +		       struct intel_memory_region *mr);
> +
>   	void (*release)(struct drm_i915_gem_object *obj);
>   
>   	const struct vm_operations_struct *mmap_ops;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index c39d982c4fa6..8f89185b6507 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>   	return &i915_ttm_bo_driver;
>   }
>   
> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
> +				struct ttm_placement *placement)
>   {
>   	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>   	struct ttm_operation_ctx ctx = {
> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		.no_wait_gpu = false,
>   	};
>   	struct sg_table *st;
> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> -	struct ttm_placement placement;
>   	int real_num_busy;
>   	int ret;
>   
> -	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> -
> -	/* Move to the requested placement. */
> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> -
>   	/* First try only the requested placement. No eviction. */
> -	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
> -	ret = ttm_bo_validate(bo, &placement, &ctx);
> +	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
> +	ret = ttm_bo_validate(bo, placement, &ctx);
>   	if (ret) {
>   		ret = i915_ttm_err_to_gem(ret);
>   		/*
> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		 * If the initial attempt fails, allow all accepted placements,
>   		 * evicting if necessary.
>   		 */
> -		placement.num_busy_placement = real_num_busy;
> -		ret = ttm_bo_validate(bo, &placement, &ctx);
> +		placement->num_busy_placement = real_num_busy;
> +		ret = ttm_bo_validate(bo, placement, &ctx);
>   		if (ret)
>   			return i915_ttm_err_to_gem(ret);
>   	}
> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		i915_ttm_adjust_gem_after_move(obj);
>   	}
>   
> -	/* Object either has a page vector or is an iomem object */
> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> -	if (IS_ERR(st))
> -		return PTR_ERR(st);
> +	if (!obj->mm.pages) {

Is this for the migration case? Where are we updating the mm.pages, 
assuming the migration step has to take care of pre-existing pages? What 
am I missing?

> +		/* Object either has a page vector or is an iomem object */
> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> +		if (IS_ERR(st))
> +			return PTR_ERR(st);
>   
> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +	}
>   
>   	return ret;
>   }
>   
> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +{
> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> +	struct ttm_placement placement;
> +
> +	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> +
> +	/* Move to the requested placement. */
> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> +
> +	return __i915_ttm_get_pages(obj, &placement);
> +}
> +
> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
> +			    struct intel_memory_region *mr)
> +{
> +	struct ttm_place requested;
> +	struct ttm_placement placement;
> +	int ret;
> +
> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
> +	placement.num_placement = 1;
> +	placement.num_busy_placement = 1;
> +	placement.placement = &requested;
> +	placement.busy_placement = &requested;
> +
> +	ret = __i915_ttm_get_pages(obj, &placement);
> +	if (ret)
> +		return ret;
> +
> +	if (obj->mm.region != mr) {
> +		i915_gem_object_release_memory_region(obj);
> +		i915_gem_object_init_memory_region(obj, mr);

Hmm, so is this not already handled by adjust_gem_after_move()?

> +	}
> +
> +	return 0;
> +}
> +
>   static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>   			       struct sg_table *st)
>   {
> @@ -814,6 +848,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,
> +	.migrate = i915_ttm_migrate,
>   	.mmap_offset = i915_ttm_mmap_offset,
>   	.mmap_ops = &vm_ops_ttm,
>   };
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> index 1070d3afdce7..f909aaa09d9c 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>   	i915_gem_object_put(obj);
>   	return ret;
>   }
> +
> +/**
> + * i915_gem_object_wait_migration - Sync an accelerated migration operation
> + * @obj: The migrating object.
> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
> + *
> + * Wait for any pending async migration operation on the object,
> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
> + * (swapin, initial clearing) initiated.
> + *
> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
> + */
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags)
> +{
> +	might_sleep();
> +	/* NOP for now. */
> +	return 0;
> +}
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 16:28     ` Matthew Auld
  0 siblings, 0 replies; 54+ messages in thread
From: Matthew Auld @ 2021-06-28 16:28 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel

On 28/06/2021 15:46, Thomas Hellström wrote:
> Introduce an interface to migrate objects between regions.
> This is primarily intended to migrate objects to LMEM for display and
> to SYSTEM for dma-buf, but might be reused in one form or another for
> performance-based migration.
> 
> v2:
> - Verify that the memory region given as an id really exists.
>    (Reported by Matthew Auld)
> - Call i915_gem_object_{init,release}_memory_region() when switching region
>    to handle also switching region lists. (Reported by Matthew Auld)
> v3:
> - Fix i915_gem_object_can_migrate() to return true if object is already in
>    the correct region, even if the object ops doesn't have a migrate()
>    callback.
> - Update typo in commit message.
> - Fix kerneldoc of i915_gem_object_wait_migration().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>   .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>   drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>   5 files changed, 188 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 07e8ff9a8aae..1c18be067b58 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
>   	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>   }
>   
> +/**
> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
> + *
> + * @obj: The object to migrate
> + * @id: The region intended to migrate to
> + *
> + * Check whether the object backend supports migration to the
> + * given region. Note that pinning may affect the ability to migrate.
> + *
> + * Return: true if migration is possible, false otherwise.
> + */
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	unsigned int num_allowed = obj->mm.n_placements;
> +	struct intel_memory_region *mr;
> +	unsigned int i;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +
> +	mr = i915->mm.regions[id];
> +	if (!mr)
> +		return false;
> +
> +	if (obj->mm.region == mr)
> +		return true;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return false;
> +
> +	if (!obj->ops->migrate)
> +		return false;
> +
> +	if (!(obj->flags & I915_BO_ALLOC_USER))
> +		return true;
> +
> +	if (num_allowed == 0)
> +		return false;
> +
> +	for (i = 0; i < num_allowed; ++i) {
> +		if (mr == obj->mm.placements[i])
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * i915_gem_object_migrate - Migrate an object to the desired region id
> + * @obj: The object to migrate.
> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
> + * not be successful in evicting other objects to make room for this object.
> + * @id: The region id to migrate to.
> + *
> + * Attempt to migrate the object to the desired memory region. The
> + * object backend must support migration and the object may not be
> + * pinned, (explicitly pinned pages or pinned vmas). The object must
> + * be locked.
> + * On successful completion, the object will have pages pointing to
> + * memory in the new region, but an async migration task may not have
> + * completed yet, and to accomplish that, i915_gem_object_wait_migration()
> + * must be called.
> + *
> + * Return: 0 on success. Negative error code on failure. In particular may
> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
> + * -EBUSY if the object is pinned.
> + */
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	struct intel_memory_region *mr;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +	assert_object_held(obj);
> +
> +	mr = i915->mm.regions[id];
> +	GEM_BUG_ON(!mr);
> +
> +	if (obj->mm.region == mr)
> +		return 0;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return -EBUSY;
> +
> +	if (!obj->ops->migrate)
> +		return -EOPNOTSUPP;
> +
> +	return obj->ops->migrate(obj, mr);
> +}
> +
>   void i915_gem_init__objects(struct drm_i915_private *i915)
>   {
>   	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index ea3224a480c4..8cbd7a5334e2 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -17,6 +17,8 @@
>   #include "i915_gem_ww.h"
>   #include "i915_vma_types.h"
>   
> +enum intel_region_id;
> +
>   /*
>    * XXX: There is a prevalence of the assumption that we fit the
>    * object's page count inside a 32bit _signed_ variable. Let's document
> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
>   
>   bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
>   
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id);
> +
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id);
> +
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags);
> +
>   #ifdef CONFIG_MMU_NOTIFIER
>   static inline bool
>   i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
> 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 441f913c87e6..ef3de2ae9723 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> @@ -18,6 +18,7 @@
>   
>   struct drm_i915_gem_object;
>   struct intel_fronbuffer;
> +struct intel_memory_region;
>   
>   /*
>    * struct i915_lut_handle tracks the fast lookups from handle to vma used
> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>   	 * delayed_free - Override the default delayed free implementation
>   	 */
>   	void (*delayed_free)(struct drm_i915_gem_object *obj);
> +
> +	/**
> +	 * migrate - Migrate object to a different region either for
> +	 * pinning or for as long as the object lock is held.
> +	 */
> +	int (*migrate)(struct drm_i915_gem_object *obj,
> +		       struct intel_memory_region *mr);
> +
>   	void (*release)(struct drm_i915_gem_object *obj);
>   
>   	const struct vm_operations_struct *mmap_ops;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index c39d982c4fa6..8f89185b6507 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>   	return &i915_ttm_bo_driver;
>   }
>   
> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
> +				struct ttm_placement *placement)
>   {
>   	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>   	struct ttm_operation_ctx ctx = {
> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		.no_wait_gpu = false,
>   	};
>   	struct sg_table *st;
> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> -	struct ttm_placement placement;
>   	int real_num_busy;
>   	int ret;
>   
> -	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> -
> -	/* Move to the requested placement. */
> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> -
>   	/* First try only the requested placement. No eviction. */
> -	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
> -	ret = ttm_bo_validate(bo, &placement, &ctx);
> +	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
> +	ret = ttm_bo_validate(bo, placement, &ctx);
>   	if (ret) {
>   		ret = i915_ttm_err_to_gem(ret);
>   		/*
> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		 * If the initial attempt fails, allow all accepted placements,
>   		 * evicting if necessary.
>   		 */
> -		placement.num_busy_placement = real_num_busy;
> -		ret = ttm_bo_validate(bo, &placement, &ctx);
> +		placement->num_busy_placement = real_num_busy;
> +		ret = ttm_bo_validate(bo, placement, &ctx);
>   		if (ret)
>   			return i915_ttm_err_to_gem(ret);
>   	}
> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>   		i915_ttm_adjust_gem_after_move(obj);
>   	}
>   
> -	/* Object either has a page vector or is an iomem object */
> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> -	if (IS_ERR(st))
> -		return PTR_ERR(st);
> +	if (!obj->mm.pages) {

Is this for the migration case? Where are we updating the mm.pages, 
assuming the migration step has to take care of pre-existing pages? What 
am I missing?

> +		/* Object either has a page vector or is an iomem object */
> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> +		if (IS_ERR(st))
> +			return PTR_ERR(st);
>   
> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +	}
>   
>   	return ret;
>   }
>   
> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +{
> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> +	struct ttm_placement placement;
> +
> +	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> +
> +	/* Move to the requested placement. */
> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> +
> +	return __i915_ttm_get_pages(obj, &placement);
> +}
> +
> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
> +			    struct intel_memory_region *mr)
> +{
> +	struct ttm_place requested;
> +	struct ttm_placement placement;
> +	int ret;
> +
> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
> +	placement.num_placement = 1;
> +	placement.num_busy_placement = 1;
> +	placement.placement = &requested;
> +	placement.busy_placement = &requested;
> +
> +	ret = __i915_ttm_get_pages(obj, &placement);
> +	if (ret)
> +		return ret;
> +
> +	if (obj->mm.region != mr) {
> +		i915_gem_object_release_memory_region(obj);
> +		i915_gem_object_init_memory_region(obj, mr);

Hmm, so is this not already handled by adjust_gem_after_move()?

> +	}
> +
> +	return 0;
> +}
> +
>   static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>   			       struct sg_table *st)
>   {
> @@ -814,6 +848,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,
> +	.migrate = i915_ttm_migrate,
>   	.mmap_offset = i915_ttm_mmap_offset,
>   	.mmap_ops = &vm_ops_ttm,
>   };
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> index 1070d3afdce7..f909aaa09d9c 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>   	i915_gem_object_put(obj);
>   	return ret;
>   }
> +
> +/**
> + * i915_gem_object_wait_migration - Sync an accelerated migration operation
> + * @obj: The migrating object.
> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
> + *
> + * Wait for any pending async migration operation on the object,
> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
> + * (swapin, initial clearing) initiated.
> + *
> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
> + */
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags)
> +{
> +	might_sleep();
> +	/* NOP for now. */
> +	return 0;
> +}
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/gem: Introduce a migrate interface (rev3)
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
                   ` (5 preceding siblings ...)
  (?)
@ 2021-06-28 16:57 ` Patchwork
  -1 siblings, 0 replies; 54+ messages in thread
From: Patchwork @ 2021-06-28 16:57 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/gem: Introduce a migrate interface (rev3)
URL   : https://patchwork.freedesktop.org/series/91890/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
673d9747bd21 drm/i915/gem: Implement object migration
fb5a2bfc3766 drm/i915/gem: Introduce a selftest for the gem object migrate functionality
-:31: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#31: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 251 lines checked
65e3941fa259 drm/i915/display: Migrate objects to LMEM if possible for display
00ac06b936ba drm/i915/gem: Fix same-driver-another-instance dma-buf export
effbc92a43a9 drm/i915/gem: Migrate to system at dma-buf map time


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915/gem: Introduce a migrate interface (rev3)
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
                   ` (6 preceding siblings ...)
  (?)
@ 2021-06-28 16:58 ` Patchwork
  -1 siblings, 0 replies; 54+ messages in thread
From: Patchwork @ 2021-06-28 16:58 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/gem: Introduce a migrate interface (rev3)
URL   : https://patchwork.freedesktop.org/series/91890/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.
-
+drivers/gpu/drm/i915/display/intel_display.c:1896:21:    expected struct i915_vma *[assigned] vma
+drivers/gpu/drm/i915/display/intel_display.c:1896:21:    got void [noderef] __iomem *[assigned] iomem
+drivers/gpu/drm/i915/display/intel_display.c:1896:21: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:27:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:27:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:27:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:32:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:32:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:49:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:49:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:49:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:56:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_engine_stats.h:56:9: warning: trying to copy expression type 31
+drivers/gpu/drm/i915/gt/intel_reset.c:1396:5: warning: context imbalance in 'intel_gt_reset_trylock' - different lock contexts for basic block
+drivers/gpu/drm/i915/gt/intel_ring_submission.c:1207:24: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/i915/i915_perf.c:1434:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/i915_perf.c:1488:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/selftests/i915_syncmap.c:80:54: warning: dubious: x | !y
+./include/asm-generic/bitops/find.h:112:45: warning: shift count is negative (-262080)
+./include/asm-generic/bitops/find.h:32:31: warning: shift count is negative (-262080)
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write8' - different lock contexts for basic block


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915/gem: Introduce a migrate interface (rev3)
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
                   ` (7 preceding siblings ...)
  (?)
@ 2021-06-28 17:27 ` Patchwork
  -1 siblings, 0 replies; 54+ messages in thread
From: Patchwork @ 2021-06-28 17:27 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 3276 bytes --]

== Series Details ==

Series: drm/i915/gem: Introduce a migrate interface (rev3)
URL   : https://patchwork.freedesktop.org/series/91890/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10284 -> Patchwork_20479
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/index.html

New tests
---------

  New tests have been introduced between CI_DRM_10284 and Patchwork_20479:

### New IGT tests (1) ###

  * igt@i915_selftest@live@gem_migrate:
    - Statuses : 33 pass(s)
    - Exec time: [0.43, 5.28] s

  

Known issues
------------

  Here are the changes found in Patchwork_20479 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_cs_nop@sync-fork-compute0:
    - fi-snb-2600:        NOTRUN -> [SKIP][1] ([fdo#109271]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/fi-snb-2600/igt@amdgpu/amd_cs_nop@sync-fork-compute0.html

  * igt@i915_selftest@live@execlists:
    - fi-bsw-nick:        [PASS][2] -> [INCOMPLETE][3] ([i915#2782] / [i915#2940])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/fi-bsw-nick/igt@i915_selftest@live@execlists.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/fi-bsw-nick/igt@i915_selftest@live@execlists.html

  * igt@runner@aborted:
    - fi-bsw-nick:        NOTRUN -> [FAIL][4] ([fdo#109271] / [i915#1436])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/fi-bsw-nick/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@hangcheck:
    - fi-snb-2600:        [INCOMPLETE][5] ([i915#2782]) -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/fi-snb-2600/igt@i915_selftest@live@hangcheck.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/fi-snb-2600/igt@i915_selftest@live@hangcheck.html

  
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1436]: https://gitlab.freedesktop.org/drm/intel/issues/1436
  [i915#2782]: https://gitlab.freedesktop.org/drm/intel/issues/2782
  [i915#2940]: https://gitlab.freedesktop.org/drm/intel/issues/2940


Participating hosts (40 -> 36)
------------------------------

  Missing    (4): fi-bsw-cyan fi-hsw-4200u fi-bdw-samus fi-bsw-n3050 


Build changes
-------------

  * Linux: CI_DRM_10284 -> Patchwork_20479

  CI-20190529: 20190529
  CI_DRM_10284: c4cc46175b38e554eab7ac3d1b95a85c79963d4a @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6120: c45c6b727c1efaced0b53620bd41c8e4facfb31f @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_20479: effbc92a43a968b385dca5695e50487386c8d33c @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

effbc92a43a9 drm/i915/gem: Migrate to system at dma-buf map time
00ac06b936ba drm/i915/gem: Fix same-driver-another-instance dma-buf export
65e3941fa259 drm/i915/display: Migrate objects to LMEM if possible for display
fb5a2bfc3766 drm/i915/gem: Introduce a selftest for the gem object migrate functionality
673d9747bd21 drm/i915/gem: Implement object migration

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/index.html

[-- Attachment #1.2: Type: text/html, Size: 4141 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 16:28     ` [Intel-gfx] " Matthew Auld
@ 2021-06-28 17:34       ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 17:34 UTC (permalink / raw)
  To: Matthew Auld, intel-gfx, dri-devel; +Cc: kernel test robot


On 6/28/21 6:28 PM, Matthew Auld wrote:
> On 28/06/2021 15:46, Thomas Hellström wrote:
>> Introduce an interface to migrate objects between regions.
>> This is primarily intended to migrate objects to LMEM for display and
>> to SYSTEM for dma-buf, but might be reused in one form or another for
>> performance-based migration.
>>
>> v2:
>> - Verify that the memory region given as an id really exists.
>>    (Reported by Matthew Auld)
>> - Call i915_gem_object_{init,release}_memory_region() when switching 
>> region
>>    to handle also switching region lists. (Reported by Matthew Auld)
>> v3:
>> - Fix i915_gem_object_can_migrate() to return true if object is 
>> already in
>>    the correct region, even if the object ops doesn't have a migrate()
>>    callback.
>> - Update typo in commit message.
>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>>   drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>   .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>   drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>   5 files changed, 188 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index 07e8ff9a8aae..1c18be067b58 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct 
>> drm_i915_gem_object *obj)
>>       return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>   }
>>   +/**
>> + * i915_gem_object_can_migrate - Whether an object likely can be 
>> migrated
>> + *
>> + * @obj: The object to migrate
>> + * @id: The region intended to migrate to
>> + *
>> + * Check whether the object backend supports migration to the
>> + * given region. Note that pinning may affect the ability to migrate.
>> + *
>> + * Return: true if migration is possible, false otherwise.
>> + */
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +                 enum intel_region_id id)
>> +{
>> +    struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +    unsigned int num_allowed = obj->mm.n_placements;
>> +    struct intel_memory_region *mr;
>> +    unsigned int i;
>> +
>> +    GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +    GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +
>> +    mr = i915->mm.regions[id];
>> +    if (!mr)
>> +        return false;
>> +
>> +    if (obj->mm.region == mr)
>> +        return true;
>> +
>> +    if (!i915_gem_object_evictable(obj))
>> +        return false;
>> +
>> +    if (!obj->ops->migrate)
>> +        return false;
>> +
>> +    if (!(obj->flags & I915_BO_ALLOC_USER))
>> +        return true;
>> +
>> +    if (num_allowed == 0)
>> +        return false;
>> +
>> +    for (i = 0; i < num_allowed; ++i) {
>> +        if (mr == obj->mm.placements[i])
>> +            return true;
>> +    }
>> +
>> +    return false;
>> +}
>> +
>> +/**
>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>> + * @obj: The object to migrate.
>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>> + * not be successful in evicting other objects to make room for this 
>> object.
>> + * @id: The region id to migrate to.
>> + *
>> + * Attempt to migrate the object to the desired memory region. The
>> + * object backend must support migration and the object may not be
>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>> + * be locked.
>> + * On successful completion, the object will have pages pointing to
>> + * memory in the new region, but an async migration task may not have
>> + * completed yet, and to accomplish that, 
>> i915_gem_object_wait_migration()
>> + * must be called.
>> + *
>> + * Return: 0 on success. Negative error code on failure. In 
>> particular may
>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock 
>> avoidance
>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>> + * -EBUSY if the object is pinned.
>> + */
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +                struct i915_gem_ww_ctx *ww,
>> +                enum intel_region_id id)
>> +{
>> +    struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +    struct intel_memory_region *mr;
>> +
>> +    GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +    GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +    assert_object_held(obj);
>> +
>> +    mr = i915->mm.regions[id];
>> +    GEM_BUG_ON(!mr);
>> +
>> +    if (obj->mm.region == mr)
>> +        return 0;
>> +
>> +    if (!i915_gem_object_evictable(obj))
>> +        return -EBUSY;
>> +
>> +    if (!obj->ops->migrate)
>> +        return -EOPNOTSUPP;
>> +
>> +    return obj->ops->migrate(obj, mr);
>> +}
>> +
>>   void i915_gem_init__objects(struct drm_i915_private *i915)
>>   {
>>       INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h 
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index ea3224a480c4..8cbd7a5334e2 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -17,6 +17,8 @@
>>   #include "i915_gem_ww.h"
>>   #include "i915_vma_types.h"
>>   +enum intel_region_id;
>> +
>>   /*
>>    * XXX: There is a prevalence of the assumption that we fit the
>>    * object's page count inside a 32bit _signed_ variable. Let's 
>> document
>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct 
>> drm_i915_gem_object *obj);
>>     bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object 
>> *obj);
>>   +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +                struct i915_gem_ww_ctx *ww,
>> +                enum intel_region_id id);
>> +
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +                 enum intel_region_id id);
>> +
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +                   unsigned int flags);
>> +
>>   #ifdef CONFIG_MMU_NOTIFIER
>>   static inline bool
>>   i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>> 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 441f913c87e6..ef3de2ae9723 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> @@ -18,6 +18,7 @@
>>     struct drm_i915_gem_object;
>>   struct intel_fronbuffer;
>> +struct intel_memory_region;
>>     /*
>>    * struct i915_lut_handle tracks the fast lookups from handle to 
>> vma used
>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>        * delayed_free - Override the default delayed free implementation
>>        */
>>       void (*delayed_free)(struct drm_i915_gem_object *obj);
>> +
>> +    /**
>> +     * migrate - Migrate object to a different region either for
>> +     * pinning or for as long as the object lock is held.
>> +     */
>> +    int (*migrate)(struct drm_i915_gem_object *obj,
>> +               struct intel_memory_region *mr);
>> +
>>       void (*release)(struct drm_i915_gem_object *obj);
>>         const struct vm_operations_struct *mmap_ops;
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index c39d982c4fa6..8f89185b6507 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>       return &i915_ttm_bo_driver;
>>   }
>>   -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>> +                struct ttm_placement *placement)
>>   {
>>       struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>       struct ttm_operation_ctx ctx = {
>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>           .no_wait_gpu = false,
>>       };
>>       struct sg_table *st;
>> -    struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> -    struct ttm_placement placement;
>>       int real_num_busy;
>>       int ret;
>>   -    GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>> -
>> -    /* Move to the requested placement. */
>> -    i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> -
>>       /* First try only the requested placement. No eviction. */
>> -    real_num_busy = fetch_and_zero(&placement.num_busy_placement);
>> -    ret = ttm_bo_validate(bo, &placement, &ctx);
>> +    real_num_busy = fetch_and_zero(&placement->num_busy_placement);
>> +    ret = ttm_bo_validate(bo, placement, &ctx);
>>       if (ret) {
>>           ret = i915_ttm_err_to_gem(ret);
>>           /*
>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>            * If the initial attempt fails, allow all accepted 
>> placements,
>>            * evicting if necessary.
>>            */
>> -        placement.num_busy_placement = real_num_busy;
>> -        ret = ttm_bo_validate(bo, &placement, &ctx);
>> +        placement->num_busy_placement = real_num_busy;
>> +        ret = ttm_bo_validate(bo, placement, &ctx);
>>           if (ret)
>>               return i915_ttm_err_to_gem(ret);
>>       }
>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>           i915_ttm_adjust_gem_after_move(obj);
>>       }
>>   -    /* Object either has a page vector or is an iomem object */
>> -    st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>> -    if (IS_ERR(st))
>> -        return PTR_ERR(st);
>> +    if (!obj->mm.pages) {
>
> Is this for the migration case? Where are we updating the mm.pages, 
> assuming the migration step has to take care of pre-existing pages? 
> What am I missing?

Hmm, yes this is for a hypotetical migration case where 
ttm_bo_validate() decided to not change placement of the object, meaning 
we migrate to the very same region that we're already in. That should be 
blocked at the gem level, so I guess we could replace this with a 
GEM_BUG_ON().

>
>> +        /* Object either has a page vector or is an iomem object */
>> +        st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : 
>> obj->ttm.cached_io_st;
>> +        if (IS_ERR(st))
>> +            return PTR_ERR(st);
>>   -    __i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>> +        __i915_gem_object_set_pages(obj, st, 
>> i915_sg_dma_sizes(st->sgl));
>> +    }
>>         return ret;
>>   }
>>   +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +{
>> +    struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> +    struct ttm_placement placement;
>> +
>> +    GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>> +
>> +    /* Move to the requested placement. */
>> +    i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> +
>> +    return __i915_ttm_get_pages(obj, &placement);
>> +}
>> +
>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>> +                struct intel_memory_region *mr)
>> +{
>> +    struct ttm_place requested;
>> +    struct ttm_placement placement;
>> +    int ret;
>> +
>> +    i915_ttm_place_from_region(mr, &requested, obj->flags);
>> +    placement.num_placement = 1;
>> +    placement.num_busy_placement = 1;
>> +    placement.placement = &requested;
>> +    placement.busy_placement = &requested;
>> +
>> +    ret = __i915_ttm_get_pages(obj, &placement);
>> +    if (ret)
>> +        return ret;
>> +
>> +    if (obj->mm.region != mr) {
>> +        i915_gem_object_release_memory_region(obj);
>> +        i915_gem_object_init_memory_region(obj, mr);
>
> Hmm, so is this not already handled by adjust_gem_after_move()?

No, not always. adjust_gem_after_move() only considers an object 
migrated and flips region if the new region is in one of the allowed 
placements. Otherwise it's considered evicted and the next get_pages() 
will revalidate into the preferred placement.

the gem_migrate interface is more flexible, and offers a possibility to 
migrate to whatever it's told, so as long as we want that behaviour, we 
need the above.

/Thomas


>
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>>                      struct sg_table *st)
>>   {
>> @@ -814,6 +848,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,
>> +    .migrate = i915_ttm_migrate,
>>       .mmap_offset = i915_ttm_mmap_offset,
>>       .mmap_ops = &vm_ops_ttm,
>>   };
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> index 1070d3afdce7..f909aaa09d9c 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void 
>> *data, struct drm_file *file)
>>       i915_gem_object_put(obj);
>>       return ret;
>>   }
>> +
>> +/**
>> + * i915_gem_object_wait_migration - Sync an accelerated migration 
>> operation
>> + * @obj: The migrating object.
>> + * @flags: waiting flags. Currently supports only 
>> I915_WAIT_INTERRUPTIBLE.
>> + *
>> + * Wait for any pending async migration operation on the object,
>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>> + * (swapin, initial clearing) initiated.
>> + *
>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during 
>> waiting.
>> + */
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +                   unsigned int flags)
>> +{
>> +    might_sleep();
>> +    /* NOP for now. */
>> +    return 0;
>> +}
>>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 17:34       ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 17:34 UTC (permalink / raw)
  To: Matthew Auld, intel-gfx, dri-devel


On 6/28/21 6:28 PM, Matthew Auld wrote:
> On 28/06/2021 15:46, Thomas Hellström wrote:
>> Introduce an interface to migrate objects between regions.
>> This is primarily intended to migrate objects to LMEM for display and
>> to SYSTEM for dma-buf, but might be reused in one form or another for
>> performance-based migration.
>>
>> v2:
>> - Verify that the memory region given as an id really exists.
>>    (Reported by Matthew Auld)
>> - Call i915_gem_object_{init,release}_memory_region() when switching 
>> region
>>    to handle also switching region lists. (Reported by Matthew Auld)
>> v3:
>> - Fix i915_gem_object_can_migrate() to return true if object is 
>> already in
>>    the correct region, even if the object ops doesn't have a migrate()
>>    callback.
>> - Update typo in commit message.
>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>>   drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>   .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>   drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>   5 files changed, 188 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index 07e8ff9a8aae..1c18be067b58 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct 
>> drm_i915_gem_object *obj)
>>       return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>   }
>>   +/**
>> + * i915_gem_object_can_migrate - Whether an object likely can be 
>> migrated
>> + *
>> + * @obj: The object to migrate
>> + * @id: The region intended to migrate to
>> + *
>> + * Check whether the object backend supports migration to the
>> + * given region. Note that pinning may affect the ability to migrate.
>> + *
>> + * Return: true if migration is possible, false otherwise.
>> + */
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +                 enum intel_region_id id)
>> +{
>> +    struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +    unsigned int num_allowed = obj->mm.n_placements;
>> +    struct intel_memory_region *mr;
>> +    unsigned int i;
>> +
>> +    GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +    GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +
>> +    mr = i915->mm.regions[id];
>> +    if (!mr)
>> +        return false;
>> +
>> +    if (obj->mm.region == mr)
>> +        return true;
>> +
>> +    if (!i915_gem_object_evictable(obj))
>> +        return false;
>> +
>> +    if (!obj->ops->migrate)
>> +        return false;
>> +
>> +    if (!(obj->flags & I915_BO_ALLOC_USER))
>> +        return true;
>> +
>> +    if (num_allowed == 0)
>> +        return false;
>> +
>> +    for (i = 0; i < num_allowed; ++i) {
>> +        if (mr == obj->mm.placements[i])
>> +            return true;
>> +    }
>> +
>> +    return false;
>> +}
>> +
>> +/**
>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>> + * @obj: The object to migrate.
>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>> + * not be successful in evicting other objects to make room for this 
>> object.
>> + * @id: The region id to migrate to.
>> + *
>> + * Attempt to migrate the object to the desired memory region. The
>> + * object backend must support migration and the object may not be
>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>> + * be locked.
>> + * On successful completion, the object will have pages pointing to
>> + * memory in the new region, but an async migration task may not have
>> + * completed yet, and to accomplish that, 
>> i915_gem_object_wait_migration()
>> + * must be called.
>> + *
>> + * Return: 0 on success. Negative error code on failure. In 
>> particular may
>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock 
>> avoidance
>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>> + * -EBUSY if the object is pinned.
>> + */
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +                struct i915_gem_ww_ctx *ww,
>> +                enum intel_region_id id)
>> +{
>> +    struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +    struct intel_memory_region *mr;
>> +
>> +    GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +    GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +    assert_object_held(obj);
>> +
>> +    mr = i915->mm.regions[id];
>> +    GEM_BUG_ON(!mr);
>> +
>> +    if (obj->mm.region == mr)
>> +        return 0;
>> +
>> +    if (!i915_gem_object_evictable(obj))
>> +        return -EBUSY;
>> +
>> +    if (!obj->ops->migrate)
>> +        return -EOPNOTSUPP;
>> +
>> +    return obj->ops->migrate(obj, mr);
>> +}
>> +
>>   void i915_gem_init__objects(struct drm_i915_private *i915)
>>   {
>>       INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h 
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index ea3224a480c4..8cbd7a5334e2 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -17,6 +17,8 @@
>>   #include "i915_gem_ww.h"
>>   #include "i915_vma_types.h"
>>   +enum intel_region_id;
>> +
>>   /*
>>    * XXX: There is a prevalence of the assumption that we fit the
>>    * object's page count inside a 32bit _signed_ variable. Let's 
>> document
>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct 
>> drm_i915_gem_object *obj);
>>     bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object 
>> *obj);
>>   +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +                struct i915_gem_ww_ctx *ww,
>> +                enum intel_region_id id);
>> +
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +                 enum intel_region_id id);
>> +
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +                   unsigned int flags);
>> +
>>   #ifdef CONFIG_MMU_NOTIFIER
>>   static inline bool
>>   i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>> 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 441f913c87e6..ef3de2ae9723 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> @@ -18,6 +18,7 @@
>>     struct drm_i915_gem_object;
>>   struct intel_fronbuffer;
>> +struct intel_memory_region;
>>     /*
>>    * struct i915_lut_handle tracks the fast lookups from handle to 
>> vma used
>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>        * delayed_free - Override the default delayed free implementation
>>        */
>>       void (*delayed_free)(struct drm_i915_gem_object *obj);
>> +
>> +    /**
>> +     * migrate - Migrate object to a different region either for
>> +     * pinning or for as long as the object lock is held.
>> +     */
>> +    int (*migrate)(struct drm_i915_gem_object *obj,
>> +               struct intel_memory_region *mr);
>> +
>>       void (*release)(struct drm_i915_gem_object *obj);
>>         const struct vm_operations_struct *mmap_ops;
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index c39d982c4fa6..8f89185b6507 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>       return &i915_ttm_bo_driver;
>>   }
>>   -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>> +                struct ttm_placement *placement)
>>   {
>>       struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>       struct ttm_operation_ctx ctx = {
>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>           .no_wait_gpu = false,
>>       };
>>       struct sg_table *st;
>> -    struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> -    struct ttm_placement placement;
>>       int real_num_busy;
>>       int ret;
>>   -    GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>> -
>> -    /* Move to the requested placement. */
>> -    i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> -
>>       /* First try only the requested placement. No eviction. */
>> -    real_num_busy = fetch_and_zero(&placement.num_busy_placement);
>> -    ret = ttm_bo_validate(bo, &placement, &ctx);
>> +    real_num_busy = fetch_and_zero(&placement->num_busy_placement);
>> +    ret = ttm_bo_validate(bo, placement, &ctx);
>>       if (ret) {
>>           ret = i915_ttm_err_to_gem(ret);
>>           /*
>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>            * If the initial attempt fails, allow all accepted 
>> placements,
>>            * evicting if necessary.
>>            */
>> -        placement.num_busy_placement = real_num_busy;
>> -        ret = ttm_bo_validate(bo, &placement, &ctx);
>> +        placement->num_busy_placement = real_num_busy;
>> +        ret = ttm_bo_validate(bo, placement, &ctx);
>>           if (ret)
>>               return i915_ttm_err_to_gem(ret);
>>       }
>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct 
>> drm_i915_gem_object *obj)
>>           i915_ttm_adjust_gem_after_move(obj);
>>       }
>>   -    /* Object either has a page vector or is an iomem object */
>> -    st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>> -    if (IS_ERR(st))
>> -        return PTR_ERR(st);
>> +    if (!obj->mm.pages) {
>
> Is this for the migration case? Where are we updating the mm.pages, 
> assuming the migration step has to take care of pre-existing pages? 
> What am I missing?

Hmm, yes this is for a hypotetical migration case where 
ttm_bo_validate() decided to not change placement of the object, meaning 
we migrate to the very same region that we're already in. That should be 
blocked at the gem level, so I guess we could replace this with a 
GEM_BUG_ON().

>
>> +        /* Object either has a page vector or is an iomem object */
>> +        st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : 
>> obj->ttm.cached_io_st;
>> +        if (IS_ERR(st))
>> +            return PTR_ERR(st);
>>   -    __i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>> +        __i915_gem_object_set_pages(obj, st, 
>> i915_sg_dma_sizes(st->sgl));
>> +    }
>>         return ret;
>>   }
>>   +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +{
>> +    struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> +    struct ttm_placement placement;
>> +
>> +    GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>> +
>> +    /* Move to the requested placement. */
>> +    i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> +
>> +    return __i915_ttm_get_pages(obj, &placement);
>> +}
>> +
>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>> +                struct intel_memory_region *mr)
>> +{
>> +    struct ttm_place requested;
>> +    struct ttm_placement placement;
>> +    int ret;
>> +
>> +    i915_ttm_place_from_region(mr, &requested, obj->flags);
>> +    placement.num_placement = 1;
>> +    placement.num_busy_placement = 1;
>> +    placement.placement = &requested;
>> +    placement.busy_placement = &requested;
>> +
>> +    ret = __i915_ttm_get_pages(obj, &placement);
>> +    if (ret)
>> +        return ret;
>> +
>> +    if (obj->mm.region != mr) {
>> +        i915_gem_object_release_memory_region(obj);
>> +        i915_gem_object_init_memory_region(obj, mr);
>
> Hmm, so is this not already handled by adjust_gem_after_move()?

No, not always. adjust_gem_after_move() only considers an object 
migrated and flips region if the new region is in one of the allowed 
placements. Otherwise it's considered evicted and the next get_pages() 
will revalidate into the preferred placement.

the gem_migrate interface is more flexible, and offers a possibility to 
migrate to whatever it's told, so as long as we want that behaviour, we 
need the above.

/Thomas


>
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>>                      struct sg_table *st)
>>   {
>> @@ -814,6 +848,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,
>> +    .migrate = i915_ttm_migrate,
>>       .mmap_offset = i915_ttm_mmap_offset,
>>       .mmap_ops = &vm_ops_ttm,
>>   };
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c 
>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> index 1070d3afdce7..f909aaa09d9c 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void 
>> *data, struct drm_file *file)
>>       i915_gem_object_put(obj);
>>       return ret;
>>   }
>> +
>> +/**
>> + * i915_gem_object_wait_migration - Sync an accelerated migration 
>> operation
>> + * @obj: The migrating object.
>> + * @flags: waiting flags. Currently supports only 
>> I915_WAIT_INTERRUPTIBLE.
>> + *
>> + * Wait for any pending async migration operation on the object,
>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>> + * (swapin, initial clearing) initiated.
>> + *
>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during 
>> waiting.
>> + */
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +                   unsigned int flags)
>> +{
>> +    might_sleep();
>> +    /* NOP for now. */
>> +    return 0;
>> +}
>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 18:11     ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 18:11 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew, lkp


>-----Original Message-----
>From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>Introduce an interface to migrate objects between regions.
>This is primarily intended to migrate objects to LMEM for display and
>to SYSTEM for dma-buf, but might be reused in one form or another for
>performance-based migration.
>
>v2:
>- Verify that the memory region given as an id really exists.
>  (Reported by Matthew Auld)
>- Call i915_gem_object_{init,release}_memory_region() when switching
>region
>  to handle also switching region lists. (Reported by Matthew Auld)
>v3:
>- Fix i915_gem_object_can_migrate() to return true if object is already in
>  the correct region, even if the object ops doesn't have a migrate()
>  callback.
>- Update typo in commit message.
>- Fix kerneldoc of i915_gem_object_wait_migration().
>
>Reported-by: kernel test robot <lkp@intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>+++++++++++++++++++
> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
> 5 files changed, 188 insertions(+), 17 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>index 07e8ff9a8aae..1c18be067b58 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>@@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>drm_i915_gem_object *obj)
> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
> }
>
>+/**
>+ * i915_gem_object_can_migrate - Whether an object likely can be migrated
>+ *
>+ * @obj: The object to migrate
>+ * @id: The region intended to migrate to
>+ *
>+ * Check whether the object backend supports migration to the
>+ * given region. Note that pinning may affect the ability to migrate.
>+ *
>+ * Return: true if migration is possible, false otherwise.
>+ */
>+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>+				 enum intel_region_id id)
>+{
>+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>+	unsigned int num_allowed = obj->mm.n_placements;
>+	struct intel_memory_region *mr;
>+	unsigned int i;
>+
>+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>+
>+	mr = i915->mm.regions[id];
>+	if (!mr)
>+		return false;
>+
>+	if (obj->mm.region == mr)
>+		return true;
>+
>+	if (!i915_gem_object_evictable(obj))
>+		return false;
>+
>+	if (!obj->ops->migrate)
>+		return false;
>+
>+	if (!(obj->flags & I915_BO_ALLOC_USER))
>+		return true;
>+
>+	if (num_allowed == 0)
>+		return false;
>+
>+	for (i = 0; i < num_allowed; ++i) {
>+		if (mr == obj->mm.placements[i])
>+			return true;
>+	}

Hi Thomas,

I am a little confused over the difference in checks between this function
and i915_gem_object_migrate().

Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
false?

So that means that under certain circumstances, you could not have a mr?

If that is the case, when?

Would that be when the I915_BO_ALLOC_USER is set?

If so, should there be a check for "non" user vs user?

Or maybe document this function pointing out why there are differences
and why?

>+	return false;
>+}
>+
>+/**
>+ * i915_gem_object_migrate - Migrate an object to the desired region id
>+ * @obj: The object to migrate.
>+ * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>+ * not be successful in evicting other objects to make room for this object.

Is the ww for future consideration?  (I don't see any use of it in the patch).

>+ * @id: The region id to migrate to.
>+ *
>+ * Attempt to migrate the object to the desired memory region. The
>+ * object backend must support migration and the object may not be
>+ * pinned, (explicitly pinned pages or pinned vmas). The object must
>+ * be locked.
>+ * On successful completion, the object will have pages pointing to
>+ * memory in the new region, but an async migration task may not have
>+ * completed yet, and to accomplish that,
>i915_gem_object_wait_migration()
>+ * must be called.
>+ *
>+ * Return: 0 on success. Negative error code on failure. In particular may
>+ * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
>+ * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>+ * -EBUSY if the object is pinned.
>+ */
>+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>+			    struct i915_gem_ww_ctx *ww,
>+			    enum intel_region_id id)
>+{
>+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>+	struct intel_memory_region *mr;
>+
>+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>+	assert_object_held(obj);
>+
>+	mr = i915->mm.regions[id];
>+	GEM_BUG_ON(!mr);
>+
>+	if (obj->mm.region == mr)
>+		return 0;
>+
>+	if (!i915_gem_object_evictable(obj))
>+		return -EBUSY;
>+
>+	if (!obj->ops->migrate)
>+		return -EOPNOTSUPP;

Why aren't you using _can_migrate here?

>+	return obj->ops->migrate(obj, mr);
>+}
>+
> void i915_gem_init__objects(struct drm_i915_private *i915)
> {
> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>index ea3224a480c4..8cbd7a5334e2 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>@@ -17,6 +17,8 @@
> #include "i915_gem_ww.h"
> #include "i915_vma_types.h"
>
>+enum intel_region_id;
>+
> /*
>  * XXX: There is a prevalence of the assumption that we fit the
>  * object's page count inside a 32bit _signed_ variable. Let's document
>@@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>drm_i915_gem_object *obj);
>
> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>*obj);
>
>+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>+			    struct i915_gem_ww_ctx *ww,
>+			    enum intel_region_id id);
>+
>+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>+				 enum intel_region_id id);
>+
>+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>+				   unsigned int flags);
>+
> #ifdef CONFIG_MMU_NOTIFIER
> static inline bool
> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>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 441f913c87e6..ef3de2ae9723 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>@@ -18,6 +18,7 @@
>
> struct drm_i915_gem_object;
> struct intel_fronbuffer;
>+struct intel_memory_region;
>
> /*
>  * struct i915_lut_handle tracks the fast lookups from handle to vma used
>@@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
> 	 * delayed_free - Override the default delayed free implementation
> 	 */
> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>+
>+	/**
>+	 * migrate - Migrate object to a different region either for
>+	 * pinning or for as long as the object lock is held.
>+	 */
>+	int (*migrate)(struct drm_i915_gem_object *obj,
>+		       struct intel_memory_region *mr);
>+
> 	void (*release)(struct drm_i915_gem_object *obj);
>
> 	const struct vm_operations_struct *mmap_ops;
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>index c39d982c4fa6..8f89185b6507 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>@@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
> 	return &i915_ttm_bo_driver;
> }
>
>-static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>+static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>+				struct ttm_placement *placement)
> {
> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
> 	struct ttm_operation_ctx ctx = {
>@@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		.no_wait_gpu = false,
> 	};
> 	struct sg_table *st;
>-	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>-	struct ttm_placement placement;
> 	int real_num_busy;
> 	int ret;
>
>-	GEM_BUG_ON(obj->mm.n_placements >
>I915_TTM_MAX_PLACEMENTS);
>-
>-	/* Move to the requested placement. */
>-	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>-
> 	/* First try only the requested placement. No eviction. */
>-	real_num_busy =
>fetch_and_zero(&placement.num_busy_placement);
>-	ret = ttm_bo_validate(bo, &placement, &ctx);
>+	real_num_busy = fetch_and_zero(&placement-
>>num_busy_placement);
>+	ret = ttm_bo_validate(bo, placement, &ctx);
> 	if (ret) {
> 		ret = i915_ttm_err_to_gem(ret);
> 		/*
>@@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		 * If the initial attempt fails, allow all accepted placements,
> 		 * evicting if necessary.
> 		 */
>-		placement.num_busy_placement = real_num_busy;
>-		ret = ttm_bo_validate(bo, &placement, &ctx);
>+		placement->num_busy_placement = real_num_busy;
>+		ret = ttm_bo_validate(bo, placement, &ctx);
> 		if (ret)
> 			return i915_ttm_err_to_gem(ret);
> 	}
>@@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		i915_ttm_adjust_gem_after_move(obj);
> 	}
>
>-	/* Object either has a page vector or is an iomem object */
>-	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>-	if (IS_ERR(st))
>-		return PTR_ERR(st);
>+	if (!obj->mm.pages) {
>+		/* Object either has a page vector or is an iomem object */
>+		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>ttm.cached_io_st;
>+		if (IS_ERR(st))
>+			return PTR_ERR(st);
>
>-	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>+		__i915_gem_object_set_pages(obj, st,
>i915_sg_dma_sizes(st->sgl));
>+	}
>
> 	return ret;
> }
>
>+static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>+{
>+	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>+	struct ttm_placement placement;
>+
>+	GEM_BUG_ON(obj->mm.n_placements >
>I915_TTM_MAX_PLACEMENTS);
>+
>+	/* Move to the requested placement. */
>+	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>+
>+	return __i915_ttm_get_pages(obj, &placement);
>+}
>+
>+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>+			    struct intel_memory_region *mr)
>+{
>+	struct ttm_place requested;
>+	struct ttm_placement placement;
>+	int ret;
>+
>+	i915_ttm_place_from_region(mr, &requested, obj->flags);
>+	placement.num_placement = 1;
>+	placement.num_busy_placement = 1;
>+	placement.placement = &requested;
>+	placement.busy_placement = &requested;
>+
>+	ret = __i915_ttm_get_pages(obj, &placement);
>+	if (ret)
>+		return ret;
>+
>+	if (obj->mm.region != mr) {
>+		i915_gem_object_release_memory_region(obj);
>+		i915_gem_object_init_memory_region(obj, mr);
>+	}

Perhaps a minor nit:

Doing this after we have done the _get_pages() just doesn't seem right.

I.e. we do work on the object, and then we init some portion of it.

Do we need to do this incase the migration/placement fails?  If so,
maybe a comment to that effect?

Thanks,

Mike

>+	return 0;
>+}
>+
> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
> 			       struct sg_table *st)
> {
>@@ -814,6 +848,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,
>+	.migrate = i915_ttm_migrate,
> 	.mmap_offset = i915_ttm_mmap_offset,
> 	.mmap_ops = &vm_ops_ttm,
> };
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>index 1070d3afdce7..f909aaa09d9c 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>@@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>*data, struct drm_file *file)
> 	i915_gem_object_put(obj);
> 	return ret;
> }
>+
>+/**
>+ * i915_gem_object_wait_migration - Sync an accelerated migration
>operation
>+ * @obj: The migrating object.
>+ * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
>+ *
>+ * Wait for any pending async migration operation on the object,
>+ * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>+ * (swapin, initial clearing) initiated.
>+ *
>+ * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>+ */
>+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>+				   unsigned int flags)
>+{
>+	might_sleep();
>+	/* NOP for now. */
>+	return 0;
>+}
>--
>2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 18:11     ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 18:11 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew


>-----Original Message-----
>From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>Introduce an interface to migrate objects between regions.
>This is primarily intended to migrate objects to LMEM for display and
>to SYSTEM for dma-buf, but might be reused in one form or another for
>performance-based migration.
>
>v2:
>- Verify that the memory region given as an id really exists.
>  (Reported by Matthew Auld)
>- Call i915_gem_object_{init,release}_memory_region() when switching
>region
>  to handle also switching region lists. (Reported by Matthew Auld)
>v3:
>- Fix i915_gem_object_can_migrate() to return true if object is already in
>  the correct region, even if the object ops doesn't have a migrate()
>  callback.
>- Update typo in commit message.
>- Fix kerneldoc of i915_gem_object_wait_migration().
>
>Reported-by: kernel test robot <lkp@intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>+++++++++++++++++++
> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
> 5 files changed, 188 insertions(+), 17 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>index 07e8ff9a8aae..1c18be067b58 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>@@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>drm_i915_gem_object *obj)
> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
> }
>
>+/**
>+ * i915_gem_object_can_migrate - Whether an object likely can be migrated
>+ *
>+ * @obj: The object to migrate
>+ * @id: The region intended to migrate to
>+ *
>+ * Check whether the object backend supports migration to the
>+ * given region. Note that pinning may affect the ability to migrate.
>+ *
>+ * Return: true if migration is possible, false otherwise.
>+ */
>+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>+				 enum intel_region_id id)
>+{
>+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>+	unsigned int num_allowed = obj->mm.n_placements;
>+	struct intel_memory_region *mr;
>+	unsigned int i;
>+
>+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>+
>+	mr = i915->mm.regions[id];
>+	if (!mr)
>+		return false;
>+
>+	if (obj->mm.region == mr)
>+		return true;
>+
>+	if (!i915_gem_object_evictable(obj))
>+		return false;
>+
>+	if (!obj->ops->migrate)
>+		return false;
>+
>+	if (!(obj->flags & I915_BO_ALLOC_USER))
>+		return true;
>+
>+	if (num_allowed == 0)
>+		return false;
>+
>+	for (i = 0; i < num_allowed; ++i) {
>+		if (mr == obj->mm.placements[i])
>+			return true;
>+	}

Hi Thomas,

I am a little confused over the difference in checks between this function
and i915_gem_object_migrate().

Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
false?

So that means that under certain circumstances, you could not have a mr?

If that is the case, when?

Would that be when the I915_BO_ALLOC_USER is set?

If so, should there be a check for "non" user vs user?

Or maybe document this function pointing out why there are differences
and why?

>+	return false;
>+}
>+
>+/**
>+ * i915_gem_object_migrate - Migrate an object to the desired region id
>+ * @obj: The object to migrate.
>+ * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>+ * not be successful in evicting other objects to make room for this object.

Is the ww for future consideration?  (I don't see any use of it in the patch).

>+ * @id: The region id to migrate to.
>+ *
>+ * Attempt to migrate the object to the desired memory region. The
>+ * object backend must support migration and the object may not be
>+ * pinned, (explicitly pinned pages or pinned vmas). The object must
>+ * be locked.
>+ * On successful completion, the object will have pages pointing to
>+ * memory in the new region, but an async migration task may not have
>+ * completed yet, and to accomplish that,
>i915_gem_object_wait_migration()
>+ * must be called.
>+ *
>+ * Return: 0 on success. Negative error code on failure. In particular may
>+ * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
>+ * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>+ * -EBUSY if the object is pinned.
>+ */
>+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>+			    struct i915_gem_ww_ctx *ww,
>+			    enum intel_region_id id)
>+{
>+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>+	struct intel_memory_region *mr;
>+
>+	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>+	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>+	assert_object_held(obj);
>+
>+	mr = i915->mm.regions[id];
>+	GEM_BUG_ON(!mr);
>+
>+	if (obj->mm.region == mr)
>+		return 0;
>+
>+	if (!i915_gem_object_evictable(obj))
>+		return -EBUSY;
>+
>+	if (!obj->ops->migrate)
>+		return -EOPNOTSUPP;

Why aren't you using _can_migrate here?

>+	return obj->ops->migrate(obj, mr);
>+}
>+
> void i915_gem_init__objects(struct drm_i915_private *i915)
> {
> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>index ea3224a480c4..8cbd7a5334e2 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>@@ -17,6 +17,8 @@
> #include "i915_gem_ww.h"
> #include "i915_vma_types.h"
>
>+enum intel_region_id;
>+
> /*
>  * XXX: There is a prevalence of the assumption that we fit the
>  * object's page count inside a 32bit _signed_ variable. Let's document
>@@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>drm_i915_gem_object *obj);
>
> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>*obj);
>
>+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>+			    struct i915_gem_ww_ctx *ww,
>+			    enum intel_region_id id);
>+
>+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>+				 enum intel_region_id id);
>+
>+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>+				   unsigned int flags);
>+
> #ifdef CONFIG_MMU_NOTIFIER
> static inline bool
> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>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 441f913c87e6..ef3de2ae9723 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>@@ -18,6 +18,7 @@
>
> struct drm_i915_gem_object;
> struct intel_fronbuffer;
>+struct intel_memory_region;
>
> /*
>  * struct i915_lut_handle tracks the fast lookups from handle to vma used
>@@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
> 	 * delayed_free - Override the default delayed free implementation
> 	 */
> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>+
>+	/**
>+	 * migrate - Migrate object to a different region either for
>+	 * pinning or for as long as the object lock is held.
>+	 */
>+	int (*migrate)(struct drm_i915_gem_object *obj,
>+		       struct intel_memory_region *mr);
>+
> 	void (*release)(struct drm_i915_gem_object *obj);
>
> 	const struct vm_operations_struct *mmap_ops;
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>index c39d982c4fa6..8f89185b6507 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>@@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
> 	return &i915_ttm_bo_driver;
> }
>
>-static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>+static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>+				struct ttm_placement *placement)
> {
> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
> 	struct ttm_operation_ctx ctx = {
>@@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		.no_wait_gpu = false,
> 	};
> 	struct sg_table *st;
>-	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>-	struct ttm_placement placement;
> 	int real_num_busy;
> 	int ret;
>
>-	GEM_BUG_ON(obj->mm.n_placements >
>I915_TTM_MAX_PLACEMENTS);
>-
>-	/* Move to the requested placement. */
>-	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>-
> 	/* First try only the requested placement. No eviction. */
>-	real_num_busy =
>fetch_and_zero(&placement.num_busy_placement);
>-	ret = ttm_bo_validate(bo, &placement, &ctx);
>+	real_num_busy = fetch_and_zero(&placement-
>>num_busy_placement);
>+	ret = ttm_bo_validate(bo, placement, &ctx);
> 	if (ret) {
> 		ret = i915_ttm_err_to_gem(ret);
> 		/*
>@@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		 * If the initial attempt fails, allow all accepted placements,
> 		 * evicting if necessary.
> 		 */
>-		placement.num_busy_placement = real_num_busy;
>-		ret = ttm_bo_validate(bo, &placement, &ctx);
>+		placement->num_busy_placement = real_num_busy;
>+		ret = ttm_bo_validate(bo, placement, &ctx);
> 		if (ret)
> 			return i915_ttm_err_to_gem(ret);
> 	}
>@@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>drm_i915_gem_object *obj)
> 		i915_ttm_adjust_gem_after_move(obj);
> 	}
>
>-	/* Object either has a page vector or is an iomem object */
>-	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>-	if (IS_ERR(st))
>-		return PTR_ERR(st);
>+	if (!obj->mm.pages) {
>+		/* Object either has a page vector or is an iomem object */
>+		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>ttm.cached_io_st;
>+		if (IS_ERR(st))
>+			return PTR_ERR(st);
>
>-	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>+		__i915_gem_object_set_pages(obj, st,
>i915_sg_dma_sizes(st->sgl));
>+	}
>
> 	return ret;
> }
>
>+static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>+{
>+	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>+	struct ttm_placement placement;
>+
>+	GEM_BUG_ON(obj->mm.n_placements >
>I915_TTM_MAX_PLACEMENTS);
>+
>+	/* Move to the requested placement. */
>+	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>+
>+	return __i915_ttm_get_pages(obj, &placement);
>+}
>+
>+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>+			    struct intel_memory_region *mr)
>+{
>+	struct ttm_place requested;
>+	struct ttm_placement placement;
>+	int ret;
>+
>+	i915_ttm_place_from_region(mr, &requested, obj->flags);
>+	placement.num_placement = 1;
>+	placement.num_busy_placement = 1;
>+	placement.placement = &requested;
>+	placement.busy_placement = &requested;
>+
>+	ret = __i915_ttm_get_pages(obj, &placement);
>+	if (ret)
>+		return ret;
>+
>+	if (obj->mm.region != mr) {
>+		i915_gem_object_release_memory_region(obj);
>+		i915_gem_object_init_memory_region(obj, mr);
>+	}

Perhaps a minor nit:

Doing this after we have done the _get_pages() just doesn't seem right.

I.e. we do work on the object, and then we init some portion of it.

Do we need to do this incase the migration/placement fails?  If so,
maybe a comment to that effect?

Thanks,

Mike

>+	return 0;
>+}
>+
> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
> 			       struct sg_table *st)
> {
>@@ -814,6 +848,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,
>+	.migrate = i915_ttm_migrate,
> 	.mmap_offset = i915_ttm_mmap_offset,
> 	.mmap_ops = &vm_ops_ttm,
> };
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>index 1070d3afdce7..f909aaa09d9c 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>@@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>*data, struct drm_file *file)
> 	i915_gem_object_put(obj);
> 	return ret;
> }
>+
>+/**
>+ * i915_gem_object_wait_migration - Sync an accelerated migration
>operation
>+ * @obj: The migrating object.
>+ * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
>+ *
>+ * Wait for any pending async migration operation on the object,
>+ * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>+ * (swapin, initial clearing) initiated.
>+ *
>+ * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>+ */
>+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>+				   unsigned int flags)
>+{
>+	might_sleep();
>+	/* NOP for now. */
>+	return 0;
>+}
>--
>2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 18:53     ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 18:53 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>
>Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the
>gem object migrate functionality
>
>From: Matthew Auld <matthew.auld@intel.com>
>
>A selftest for the gem object migrate functionality. Slightly adapted
>from the original by Matthew to the new interface and new fill blit
>code.
>
>Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
> .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>++++++++++++++++++
> .../drm/i915/selftests/i915_live_selftests.h  |   1 +
> 3 files changed, 239 insertions(+)
> create mode 100644
>drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>index 1c18be067b58..ff147fd59874 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>@@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>i915_gem_object_funcs = {
> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> #include "selftests/huge_gem_object.c"
> #include "selftests/huge_pages.c"
>+#include "selftests/i915_gem_migrate.c"
> #include "selftests/i915_gem_object.c"
> #include "selftests/i915_gem_coherency.c"
> #endif
>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>new file mode 100644
>index 000000000000..a437b66f64d9
>--- /dev/null
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>@@ -0,0 +1,237 @@
>+// SPDX-License-Identifier: MIT
>+/*
>+ * Copyright © 2020-2021 Intel Corporation
>+ */
>+
>+#include "gt/intel_migrate.h"
>+
>+static int igt_smem_create_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	int err = 0;
>+
>+	/* Switch object backing-store on create */
>+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	for_i915_gem_ww(&ww, err, true) {
>+		err = i915_gem_object_lock(obj, &ww);
>+		if (err)
>+			continue;
>+
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM)) {
>+			err = -EINVAL;
>+			continue;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, &ww,
>INTEL_REGION_SMEM);
>+		if (err)
>+			continue;
>+
>+		err = i915_gem_object_pin_pages(obj);
>+		if (err)
>+			continue;
>+
>+		if (i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM))
>+			err = -EINVAL;
>+
>+		i915_gem_object_unpin_pages(obj);
>+	}
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+static int igt_lmem_create_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	int err = 0;
>+
>+	/* Switch object backing-store on create */
>+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	for_i915_gem_ww(&ww, err, true) {
>+		err = i915_gem_object_lock(obj, &ww);
>+		if (err)
>+			continue;
>+
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM)) {
>+			err = -EINVAL;
>+			continue;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, &ww,
>INTEL_REGION_LMEM);
>+		if (err)
>+			continue;
>+
>+		err = i915_gem_object_pin_pages(obj);
>+		if (err)
>+			continue;
>+
>+		if (i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM))
>+			err = -EINVAL;
>+
>+		i915_gem_object_unpin_pages(obj);
>+	}
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>+				  struct drm_i915_gem_object *obj)
>+{
>+	int err;
>+
>+	err = i915_gem_object_lock(obj, ww);
>+	if (err)
>+		return err;
>+
>+	err = i915_gem_object_wait(obj,
>+				   I915_WAIT_INTERRUPTIBLE |
>+				   I915_WAIT_PRIORITY |
>+				   I915_WAIT_ALL,
>+				   MAX_SCHEDULE_TIMEOUT);
>+	if (err)
>+		return err;
>+
>+	if (i915_gem_object_is_lmem(obj)) {
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM)) {

I don't see any  testing of the parameter num_allowed.

Is that done somewhere else?

Mike

>+			pr_err("object can't migrate to smem.\n");
>+			return -EINVAL;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, ww,
>INTEL_REGION_SMEM);
>+		if (err) {
>+			pr_err("Object failed migration to smem\n");
>+			if (err)
>+				return err;
>+		}
>+
>+		if (i915_gem_object_is_lmem(obj)) {
>+			pr_err("object still backed by lmem\n");
>+			err = -EINVAL;
>+		}
>+
>+		if (!i915_gem_object_has_struct_page(obj)) {
>+			pr_err("object not backed by struct page\n");
>+			err = -EINVAL;
>+		}
>+
>+	} else {
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM)) {
>+			pr_err("object can't migrate to lmem.\n");
>+			return -EINVAL;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, ww,
>INTEL_REGION_LMEM);
>+		if (err) {
>+			pr_err("Object failed migration to lmem\n");
>+			if (err)
>+				return err;
>+		}
>+
>+		if (i915_gem_object_has_struct_page(obj)) {
>+			pr_err("object still backed by struct page\n");
>+			err = -EINVAL;
>+		}
>+
>+		if (!i915_gem_object_is_lmem(obj)) {
>+			pr_err("object not backed by lmem\n");
>+			err = -EINVAL;
>+		}
>+	}
>+
>+	return err;
>+}
>+
>+static int igt_lmem_pages_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	struct i915_request *rq;
>+	int err;
>+	int i;
>+
>+	/* From LMEM to shmem and back again */
>+
>+	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	err = i915_gem_object_lock(obj, NULL);
>+	if (err)
>+		goto out_put;
>+
>+	err = ____i915_gem_object_get_pages(obj);
>+	if (err) {
>+		i915_gem_object_unlock(obj);
>+		goto out_put;
>+	}
>+
>+	err = intel_context_migrate_clear(gt->migrate.context, NULL,
>+					  obj->mm.pages->sgl, obj-
>>cache_level,
>+					  i915_gem_object_is_lmem(obj),
>+					  0, &rq);
>+	if (rq) {
>+		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
>+		i915_request_put(rq);
>+	}
>+	i915_gem_object_unlock(obj);
>+	if (err)
>+		goto out_put;
>+
>+	for (i = 1; i <= 4; ++i) {
>+		for_i915_gem_ww(&ww, err, true) {
>+			err = lmem_pages_migrate_one(&ww, obj);
>+			if (err)
>+				continue;
>+
>+			err = i915_gem_object_wait_migration(obj, true);
>+			if (err)
>+				continue;
>+
>+			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
>+						  obj->mm.pages->sgl,
>+						  obj->cache_level,
>+
>i915_gem_object_is_lmem(obj),
>+						  0xdeadbeaf, &rq);
>+			if (rq) {
>+				dma_resv_add_excl_fence(obj->base.resv,
>+							&rq->fence);
>+				i915_request_put(rq);
>+			}
>+		}
>+		if (err)
>+			break;
>+	}
>+out_put:
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
>+{
>+	static const struct i915_subtest tests[] = {
>+		SUBTEST(igt_smem_create_migrate),
>+		SUBTEST(igt_lmem_create_migrate),
>+		SUBTEST(igt_lmem_pages_migrate),
>+	};
>+
>+	if (!HAS_LMEM(i915))
>+		return 0;
>+
>+	return intel_gt_live_subtests(tests, &i915->gt);
>+}
>diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>index a68197cf1044..e2fd1b61af71 100644
>--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>@@ -40,6 +40,7 @@ selftest(hugepages,
>i915_gem_huge_page_live_selftests)
> selftest(gem_contexts, i915_gem_context_live_selftests)
> selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
> selftest(client, i915_gem_client_blt_live_selftests)
>+selftest(gem_migrate, i915_gem_migrate_live_selftests)
> selftest(reset, intel_reset_live_selftests)
> selftest(memory_region, intel_memory_region_live_selftests)
> selftest(hangcheck, intel_hangcheck_live_selftests)
>--
>2.31.1
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 18:53     ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 18:53 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>
>Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the
>gem object migrate functionality
>
>From: Matthew Auld <matthew.auld@intel.com>
>
>A selftest for the gem object migrate functionality. Slightly adapted
>from the original by Matthew to the new interface and new fill blit
>code.
>
>Co-developed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
> .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>++++++++++++++++++
> .../drm/i915/selftests/i915_live_selftests.h  |   1 +
> 3 files changed, 239 insertions(+)
> create mode 100644
>drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>index 1c18be067b58..ff147fd59874 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>@@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>i915_gem_object_funcs = {
> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> #include "selftests/huge_gem_object.c"
> #include "selftests/huge_pages.c"
>+#include "selftests/i915_gem_migrate.c"
> #include "selftests/i915_gem_object.c"
> #include "selftests/i915_gem_coherency.c"
> #endif
>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>new file mode 100644
>index 000000000000..a437b66f64d9
>--- /dev/null
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>@@ -0,0 +1,237 @@
>+// SPDX-License-Identifier: MIT
>+/*
>+ * Copyright © 2020-2021 Intel Corporation
>+ */
>+
>+#include "gt/intel_migrate.h"
>+
>+static int igt_smem_create_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	int err = 0;
>+
>+	/* Switch object backing-store on create */
>+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	for_i915_gem_ww(&ww, err, true) {
>+		err = i915_gem_object_lock(obj, &ww);
>+		if (err)
>+			continue;
>+
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM)) {
>+			err = -EINVAL;
>+			continue;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, &ww,
>INTEL_REGION_SMEM);
>+		if (err)
>+			continue;
>+
>+		err = i915_gem_object_pin_pages(obj);
>+		if (err)
>+			continue;
>+
>+		if (i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM))
>+			err = -EINVAL;
>+
>+		i915_gem_object_unpin_pages(obj);
>+	}
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+static int igt_lmem_create_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	int err = 0;
>+
>+	/* Switch object backing-store on create */
>+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	for_i915_gem_ww(&ww, err, true) {
>+		err = i915_gem_object_lock(obj, &ww);
>+		if (err)
>+			continue;
>+
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM)) {
>+			err = -EINVAL;
>+			continue;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, &ww,
>INTEL_REGION_LMEM);
>+		if (err)
>+			continue;
>+
>+		err = i915_gem_object_pin_pages(obj);
>+		if (err)
>+			continue;
>+
>+		if (i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM))
>+			err = -EINVAL;
>+
>+		i915_gem_object_unpin_pages(obj);
>+	}
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>+				  struct drm_i915_gem_object *obj)
>+{
>+	int err;
>+
>+	err = i915_gem_object_lock(obj, ww);
>+	if (err)
>+		return err;
>+
>+	err = i915_gem_object_wait(obj,
>+				   I915_WAIT_INTERRUPTIBLE |
>+				   I915_WAIT_PRIORITY |
>+				   I915_WAIT_ALL,
>+				   MAX_SCHEDULE_TIMEOUT);
>+	if (err)
>+		return err;
>+
>+	if (i915_gem_object_is_lmem(obj)) {
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_SMEM)) {

I don't see any  testing of the parameter num_allowed.

Is that done somewhere else?

Mike

>+			pr_err("object can't migrate to smem.\n");
>+			return -EINVAL;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, ww,
>INTEL_REGION_SMEM);
>+		if (err) {
>+			pr_err("Object failed migration to smem\n");
>+			if (err)
>+				return err;
>+		}
>+
>+		if (i915_gem_object_is_lmem(obj)) {
>+			pr_err("object still backed by lmem\n");
>+			err = -EINVAL;
>+		}
>+
>+		if (!i915_gem_object_has_struct_page(obj)) {
>+			pr_err("object not backed by struct page\n");
>+			err = -EINVAL;
>+		}
>+
>+	} else {
>+		if (!i915_gem_object_can_migrate(obj,
>INTEL_REGION_LMEM)) {
>+			pr_err("object can't migrate to lmem.\n");
>+			return -EINVAL;
>+		}
>+
>+		err = i915_gem_object_migrate(obj, ww,
>INTEL_REGION_LMEM);
>+		if (err) {
>+			pr_err("Object failed migration to lmem\n");
>+			if (err)
>+				return err;
>+		}
>+
>+		if (i915_gem_object_has_struct_page(obj)) {
>+			pr_err("object still backed by struct page\n");
>+			err = -EINVAL;
>+		}
>+
>+		if (!i915_gem_object_is_lmem(obj)) {
>+			pr_err("object not backed by lmem\n");
>+			err = -EINVAL;
>+		}
>+	}
>+
>+	return err;
>+}
>+
>+static int igt_lmem_pages_migrate(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct drm_i915_private *i915 = gt->i915;
>+	struct drm_i915_gem_object *obj;
>+	struct i915_gem_ww_ctx ww;
>+	struct i915_request *rq;
>+	int err;
>+	int i;
>+
>+	/* From LMEM to shmem and back again */
>+
>+	obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
>+	if (IS_ERR(obj))
>+		return PTR_ERR(obj);
>+
>+	err = i915_gem_object_lock(obj, NULL);
>+	if (err)
>+		goto out_put;
>+
>+	err = ____i915_gem_object_get_pages(obj);
>+	if (err) {
>+		i915_gem_object_unlock(obj);
>+		goto out_put;
>+	}
>+
>+	err = intel_context_migrate_clear(gt->migrate.context, NULL,
>+					  obj->mm.pages->sgl, obj-
>>cache_level,
>+					  i915_gem_object_is_lmem(obj),
>+					  0, &rq);
>+	if (rq) {
>+		dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
>+		i915_request_put(rq);
>+	}
>+	i915_gem_object_unlock(obj);
>+	if (err)
>+		goto out_put;
>+
>+	for (i = 1; i <= 4; ++i) {
>+		for_i915_gem_ww(&ww, err, true) {
>+			err = lmem_pages_migrate_one(&ww, obj);
>+			if (err)
>+				continue;
>+
>+			err = i915_gem_object_wait_migration(obj, true);
>+			if (err)
>+				continue;
>+
>+			err = intel_migrate_clear(&gt->migrate, &ww, NULL,
>+						  obj->mm.pages->sgl,
>+						  obj->cache_level,
>+
>i915_gem_object_is_lmem(obj),
>+						  0xdeadbeaf, &rq);
>+			if (rq) {
>+				dma_resv_add_excl_fence(obj->base.resv,
>+							&rq->fence);
>+				i915_request_put(rq);
>+			}
>+		}
>+		if (err)
>+			break;
>+	}
>+out_put:
>+	i915_gem_object_put(obj);
>+
>+	return err;
>+}
>+
>+int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
>+{
>+	static const struct i915_subtest tests[] = {
>+		SUBTEST(igt_smem_create_migrate),
>+		SUBTEST(igt_lmem_create_migrate),
>+		SUBTEST(igt_lmem_pages_migrate),
>+	};
>+
>+	if (!HAS_LMEM(i915))
>+		return 0;
>+
>+	return intel_gt_live_subtests(tests, &i915->gt);
>+}
>diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>index a68197cf1044..e2fd1b61af71 100644
>--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>@@ -40,6 +40,7 @@ selftest(hugepages,
>i915_gem_huge_page_live_selftests)
> selftest(gem_contexts, i915_gem_context_live_selftests)
> selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
> selftest(client, i915_gem_client_blt_live_selftests)
>+selftest(gem_migrate, i915_gem_migrate_live_selftests)
> selftest(reset, intel_reset_live_selftests)
> selftest(memory_region, intel_memory_region_live_selftests)
> selftest(hangcheck, intel_hangcheck_live_selftests)
>--
>2.31.1
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 18:11     ` [Intel-gfx] " Ruhl, Michael J
@ 2021-06-28 19:02       ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:02 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew, lkp


On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>> Thomas Hellström
>> Sent: Monday, June 28, 2021 10:46 AM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>
>> Introduce an interface to migrate objects between regions.
>> This is primarily intended to migrate objects to LMEM for display and
>> to SYSTEM for dma-buf, but might be reused in one form or another for
>> performance-based migration.
>>
>> v2:
>> - Verify that the memory region given as an id really exists.
>>   (Reported by Matthew Auld)
>> - Call i915_gem_object_{init,release}_memory_region() when switching
>> region
>>   to handle also switching region lists. (Reported by Matthew Auld)
>> v3:
>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>   the correct region, even if the object ops doesn't have a migrate()
>>   callback.
>> - Update typo in commit message.
>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>> +++++++++++++++++++
>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index 07e8ff9a8aae..1c18be067b58 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>> drm_i915_gem_object *obj)
>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>> }
>>
>> +/**
>> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
>> + *
>> + * @obj: The object to migrate
>> + * @id: The region intended to migrate to
>> + *
>> + * Check whether the object backend supports migration to the
>> + * given region. Note that pinning may affect the ability to migrate.
>> + *
>> + * Return: true if migration is possible, false otherwise.
>> + */
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +				 enum intel_region_id id)
>> +{
>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +	unsigned int num_allowed = obj->mm.n_placements;
>> +	struct intel_memory_region *mr;
>> +	unsigned int i;
>> +
>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +
>> +	mr = i915->mm.regions[id];
>> +	if (!mr)
>> +		return false;
>> +
>> +	if (obj->mm.region == mr)
>> +		return true;
>> +
>> +	if (!i915_gem_object_evictable(obj))
>> +		return false;
>> +
>> +	if (!obj->ops->migrate)
>> +		return false;
>> +
>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>> +		return true;
>> +
>> +	if (num_allowed == 0)
>> +		return false;
>> +
>> +	for (i = 0; i < num_allowed; ++i) {
>> +		if (mr == obj->mm.placements[i])
>> +			return true;
>> +	}
> Hi Thomas,
>
> I am a little confused over the difference in checks between this function
> and i915_gem_object_migrate().
>
> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
> false?
>
> So that means that under certain circumstances, you could not have a mr?
>
> If that is the case, when?
>
> Would that be when the I915_BO_ALLOC_USER is set?
>
> If so, should there be a check for "non" user vs user?
>
> Or maybe document this function pointing out why there are differences
> and why?

Yes, I'll give it some more documentation. The basic idea is that the 
above function also could be
used to validate user supplied data, whereas there might be cases where 
we want to use the gem_object_migrate() function and override the above.


>
>> +	return false;
>> +}
>> +
>> +/**
>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>> + * @obj: The object to migrate.
>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>> + * not be successful in evicting other objects to make room for this object.
> Is the ww for future consideration?  (I don't see any use of it in the patch).

Yes, but it will remain optional.


>
>> + * @id: The region id to migrate to.
>> + *
>> + * Attempt to migrate the object to the desired memory region. The
>> + * object backend must support migration and the object may not be
>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>> + * be locked.
>> + * On successful completion, the object will have pages pointing to
>> + * memory in the new region, but an async migration task may not have
>> + * completed yet, and to accomplish that,
>> i915_gem_object_wait_migration()
>> + * must be called.
>> + *
>> + * Return: 0 on success. Negative error code on failure. In particular may
>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>> + * -EBUSY if the object is pinned.
>> + */
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +			    struct i915_gem_ww_ctx *ww,
>> +			    enum intel_region_id id)
>> +{
>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +	struct intel_memory_region *mr;
>> +
>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +	assert_object_held(obj);
>> +
>> +	mr = i915->mm.regions[id];
>> +	GEM_BUG_ON(!mr);
>> +
>> +	if (obj->mm.region == mr)
>> +		return 0;
>> +
>> +	if (!i915_gem_object_evictable(obj))
>> +		return -EBUSY;
>> +
>> +	if (!obj->ops->migrate)
>> +		return -EOPNOTSUPP;
> Why aren't you using _can_migrate here?

It's just in case we want to override. I'll add some more comments about 
this.

>
>> +	return obj->ops->migrate(obj, mr);
>> +}
>> +
>> void i915_gem_init__objects(struct drm_i915_private *i915)
>> {
>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index ea3224a480c4..8cbd7a5334e2 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -17,6 +17,8 @@
>> #include "i915_gem_ww.h"
>> #include "i915_vma_types.h"
>>
>> +enum intel_region_id;
>> +
>> /*
>>   * XXX: There is a prevalence of the assumption that we fit the
>>   * object's page count inside a 32bit _signed_ variable. Let's document
>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>> drm_i915_gem_object *obj);
>>
>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>> *obj);
>>
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +			    struct i915_gem_ww_ctx *ww,
>> +			    enum intel_region_id id);
>> +
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +				 enum intel_region_id id);
>> +
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +				   unsigned int flags);
>> +
>> #ifdef CONFIG_MMU_NOTIFIER
>> static inline bool
>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>> 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 441f913c87e6..ef3de2ae9723 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> @@ -18,6 +18,7 @@
>>
>> struct drm_i915_gem_object;
>> struct intel_fronbuffer;
>> +struct intel_memory_region;
>>
>> /*
>>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>> 	 * delayed_free - Override the default delayed free implementation
>> 	 */
>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>> +
>> +	/**
>> +	 * migrate - Migrate object to a different region either for
>> +	 * pinning or for as long as the object lock is held.
>> +	 */
>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>> +		       struct intel_memory_region *mr);
>> +
>> 	void (*release)(struct drm_i915_gem_object *obj);
>>
>> 	const struct vm_operations_struct *mmap_ops;
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index c39d982c4fa6..8f89185b6507 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>> 	return &i915_ttm_bo_driver;
>> }
>>
>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>> +				struct ttm_placement *placement)
>> {
>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>> 	struct ttm_operation_ctx ctx = {
>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		.no_wait_gpu = false,
>> 	};
>> 	struct sg_table *st;
>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> -	struct ttm_placement placement;
>> 	int real_num_busy;
>> 	int ret;
>>
>> -	GEM_BUG_ON(obj->mm.n_placements >
>> I915_TTM_MAX_PLACEMENTS);
>> -
>> -	/* Move to the requested placement. */
>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> -
>> 	/* First try only the requested placement. No eviction. */
>> -	real_num_busy =
>> fetch_and_zero(&placement.num_busy_placement);
>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>> +	real_num_busy = fetch_and_zero(&placement-
>>> num_busy_placement);
>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>> 	if (ret) {
>> 		ret = i915_ttm_err_to_gem(ret);
>> 		/*
>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		 * If the initial attempt fails, allow all accepted placements,
>> 		 * evicting if necessary.
>> 		 */
>> -		placement.num_busy_placement = real_num_busy;
>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>> +		placement->num_busy_placement = real_num_busy;
>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>> 		if (ret)
>> 			return i915_ttm_err_to_gem(ret);
>> 	}
>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		i915_ttm_adjust_gem_after_move(obj);
>> 	}
>>
>> -	/* Object either has a page vector or is an iomem object */
>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>> -	if (IS_ERR(st))
>> -		return PTR_ERR(st);
>> +	if (!obj->mm.pages) {
>> +		/* Object either has a page vector or is an iomem object */
>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>> ttm.cached_io_st;
>> +		if (IS_ERR(st))
>> +			return PTR_ERR(st);
>>
>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>> +		__i915_gem_object_set_pages(obj, st,
>> i915_sg_dma_sizes(st->sgl));
>> +	}
>>
>> 	return ret;
>> }
>>
>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +{
>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> +	struct ttm_placement placement;
>> +
>> +	GEM_BUG_ON(obj->mm.n_placements >
>> I915_TTM_MAX_PLACEMENTS);
>> +
>> +	/* Move to the requested placement. */
>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> +
>> +	return __i915_ttm_get_pages(obj, &placement);
>> +}
>> +
>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>> +			    struct intel_memory_region *mr)
>> +{
>> +	struct ttm_place requested;
>> +	struct ttm_placement placement;
>> +	int ret;
>> +
>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>> +	placement.num_placement = 1;
>> +	placement.num_busy_placement = 1;
>> +	placement.placement = &requested;
>> +	placement.busy_placement = &requested;
>> +
>> +	ret = __i915_ttm_get_pages(obj, &placement);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (obj->mm.region != mr) {
>> +		i915_gem_object_release_memory_region(obj);
>> +		i915_gem_object_init_memory_region(obj, mr);
>> +	}
> Perhaps a minor nit:
>
> Doing this after we have done the _get_pages() just doesn't seem right.
>
> I.e. we do work on the object, and then we init some portion of it.
>
> Do we need to do this incase the migration/placement fails?  If so,
> maybe a comment to that effect?

This is simply switching memory region under the lock, and to also move 
to another memory region list. Is it the naming _release_ and _init_ 
that is confusing?

/Thomas


>
> Thanks,
>
> Mike
>
>> +	return 0;
>> +}
>> +
>> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>> 			       struct sg_table *st)
>> {
>> @@ -814,6 +848,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,
>> +	.migrate = i915_ttm_migrate,
>> 	.mmap_offset = i915_ttm_mmap_offset,
>> 	.mmap_ops = &vm_ops_ttm,
>> };
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> index 1070d3afdce7..f909aaa09d9c 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>> *data, struct drm_file *file)
>> 	i915_gem_object_put(obj);
>> 	return ret;
>> }
>> +
>> +/**
>> + * i915_gem_object_wait_migration - Sync an accelerated migration
>> operation
>> + * @obj: The migrating object.
>> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
>> + *
>> + * Wait for any pending async migration operation on the object,
>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>> + * (swapin, initial clearing) initiated.
>> + *
>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>> + */
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +				   unsigned int flags)
>> +{
>> +	might_sleep();
>> +	/* NOP for now. */
>> +	return 0;
>> +}
>> --
>> 2.31.1

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 19:02       ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:02 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>> Thomas Hellström
>> Sent: Monday, June 28, 2021 10:46 AM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>
>> Introduce an interface to migrate objects between regions.
>> This is primarily intended to migrate objects to LMEM for display and
>> to SYSTEM for dma-buf, but might be reused in one form or another for
>> performance-based migration.
>>
>> v2:
>> - Verify that the memory region given as an id really exists.
>>   (Reported by Matthew Auld)
>> - Call i915_gem_object_{init,release}_memory_region() when switching
>> region
>>   to handle also switching region lists. (Reported by Matthew Auld)
>> v3:
>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>   the correct region, even if the object ops doesn't have a migrate()
>>   callback.
>> - Update typo in commit message.
>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>> +++++++++++++++++++
>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index 07e8ff9a8aae..1c18be067b58 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>> drm_i915_gem_object *obj)
>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>> }
>>
>> +/**
>> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
>> + *
>> + * @obj: The object to migrate
>> + * @id: The region intended to migrate to
>> + *
>> + * Check whether the object backend supports migration to the
>> + * given region. Note that pinning may affect the ability to migrate.
>> + *
>> + * Return: true if migration is possible, false otherwise.
>> + */
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +				 enum intel_region_id id)
>> +{
>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +	unsigned int num_allowed = obj->mm.n_placements;
>> +	struct intel_memory_region *mr;
>> +	unsigned int i;
>> +
>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +
>> +	mr = i915->mm.regions[id];
>> +	if (!mr)
>> +		return false;
>> +
>> +	if (obj->mm.region == mr)
>> +		return true;
>> +
>> +	if (!i915_gem_object_evictable(obj))
>> +		return false;
>> +
>> +	if (!obj->ops->migrate)
>> +		return false;
>> +
>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>> +		return true;
>> +
>> +	if (num_allowed == 0)
>> +		return false;
>> +
>> +	for (i = 0; i < num_allowed; ++i) {
>> +		if (mr == obj->mm.placements[i])
>> +			return true;
>> +	}
> Hi Thomas,
>
> I am a little confused over the difference in checks between this function
> and i915_gem_object_migrate().
>
> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
> false?
>
> So that means that under certain circumstances, you could not have a mr?
>
> If that is the case, when?
>
> Would that be when the I915_BO_ALLOC_USER is set?
>
> If so, should there be a check for "non" user vs user?
>
> Or maybe document this function pointing out why there are differences
> and why?

Yes, I'll give it some more documentation. The basic idea is that the 
above function also could be
used to validate user supplied data, whereas there might be cases where 
we want to use the gem_object_migrate() function and override the above.


>
>> +	return false;
>> +}
>> +
>> +/**
>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>> + * @obj: The object to migrate.
>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>> + * not be successful in evicting other objects to make room for this object.
> Is the ww for future consideration?  (I don't see any use of it in the patch).

Yes, but it will remain optional.


>
>> + * @id: The region id to migrate to.
>> + *
>> + * Attempt to migrate the object to the desired memory region. The
>> + * object backend must support migration and the object may not be
>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>> + * be locked.
>> + * On successful completion, the object will have pages pointing to
>> + * memory in the new region, but an async migration task may not have
>> + * completed yet, and to accomplish that,
>> i915_gem_object_wait_migration()
>> + * must be called.
>> + *
>> + * Return: 0 on success. Negative error code on failure. In particular may
>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>> + * -EBUSY if the object is pinned.
>> + */
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +			    struct i915_gem_ww_ctx *ww,
>> +			    enum intel_region_id id)
>> +{
>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>> +	struct intel_memory_region *mr;
>> +
>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>> +	assert_object_held(obj);
>> +
>> +	mr = i915->mm.regions[id];
>> +	GEM_BUG_ON(!mr);
>> +
>> +	if (obj->mm.region == mr)
>> +		return 0;
>> +
>> +	if (!i915_gem_object_evictable(obj))
>> +		return -EBUSY;
>> +
>> +	if (!obj->ops->migrate)
>> +		return -EOPNOTSUPP;
> Why aren't you using _can_migrate here?

It's just in case we want to override. I'll add some more comments about 
this.

>
>> +	return obj->ops->migrate(obj, mr);
>> +}
>> +
>> void i915_gem_init__objects(struct drm_i915_private *i915)
>> {
>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index ea3224a480c4..8cbd7a5334e2 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -17,6 +17,8 @@
>> #include "i915_gem_ww.h"
>> #include "i915_vma_types.h"
>>
>> +enum intel_region_id;
>> +
>> /*
>>   * XXX: There is a prevalence of the assumption that we fit the
>>   * object's page count inside a 32bit _signed_ variable. Let's document
>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>> drm_i915_gem_object *obj);
>>
>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>> *obj);
>>
>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>> +			    struct i915_gem_ww_ctx *ww,
>> +			    enum intel_region_id id);
>> +
>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>> +				 enum intel_region_id id);
>> +
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +				   unsigned int flags);
>> +
>> #ifdef CONFIG_MMU_NOTIFIER
>> static inline bool
>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>> 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 441f913c87e6..ef3de2ae9723 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> @@ -18,6 +18,7 @@
>>
>> struct drm_i915_gem_object;
>> struct intel_fronbuffer;
>> +struct intel_memory_region;
>>
>> /*
>>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>> 	 * delayed_free - Override the default delayed free implementation
>> 	 */
>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>> +
>> +	/**
>> +	 * migrate - Migrate object to a different region either for
>> +	 * pinning or for as long as the object lock is held.
>> +	 */
>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>> +		       struct intel_memory_region *mr);
>> +
>> 	void (*release)(struct drm_i915_gem_object *obj);
>>
>> 	const struct vm_operations_struct *mmap_ops;
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index c39d982c4fa6..8f89185b6507 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>> 	return &i915_ttm_bo_driver;
>> }
>>
>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>> +				struct ttm_placement *placement)
>> {
>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>> 	struct ttm_operation_ctx ctx = {
>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		.no_wait_gpu = false,
>> 	};
>> 	struct sg_table *st;
>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> -	struct ttm_placement placement;
>> 	int real_num_busy;
>> 	int ret;
>>
>> -	GEM_BUG_ON(obj->mm.n_placements >
>> I915_TTM_MAX_PLACEMENTS);
>> -
>> -	/* Move to the requested placement. */
>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> -
>> 	/* First try only the requested placement. No eviction. */
>> -	real_num_busy =
>> fetch_and_zero(&placement.num_busy_placement);
>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>> +	real_num_busy = fetch_and_zero(&placement-
>>> num_busy_placement);
>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>> 	if (ret) {
>> 		ret = i915_ttm_err_to_gem(ret);
>> 		/*
>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		 * If the initial attempt fails, allow all accepted placements,
>> 		 * evicting if necessary.
>> 		 */
>> -		placement.num_busy_placement = real_num_busy;
>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>> +		placement->num_busy_placement = real_num_busy;
>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>> 		if (ret)
>> 			return i915_ttm_err_to_gem(ret);
>> 	}
>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>> drm_i915_gem_object *obj)
>> 		i915_ttm_adjust_gem_after_move(obj);
>> 	}
>>
>> -	/* Object either has a page vector or is an iomem object */
>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>> -	if (IS_ERR(st))
>> -		return PTR_ERR(st);
>> +	if (!obj->mm.pages) {
>> +		/* Object either has a page vector or is an iomem object */
>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>> ttm.cached_io_st;
>> +		if (IS_ERR(st))
>> +			return PTR_ERR(st);
>>
>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>> +		__i915_gem_object_set_pages(obj, st,
>> i915_sg_dma_sizes(st->sgl));
>> +	}
>>
>> 	return ret;
>> }
>>
>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>> +{
>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>> +	struct ttm_placement placement;
>> +
>> +	GEM_BUG_ON(obj->mm.n_placements >
>> I915_TTM_MAX_PLACEMENTS);
>> +
>> +	/* Move to the requested placement. */
>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>> +
>> +	return __i915_ttm_get_pages(obj, &placement);
>> +}
>> +
>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>> +			    struct intel_memory_region *mr)
>> +{
>> +	struct ttm_place requested;
>> +	struct ttm_placement placement;
>> +	int ret;
>> +
>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>> +	placement.num_placement = 1;
>> +	placement.num_busy_placement = 1;
>> +	placement.placement = &requested;
>> +	placement.busy_placement = &requested;
>> +
>> +	ret = __i915_ttm_get_pages(obj, &placement);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (obj->mm.region != mr) {
>> +		i915_gem_object_release_memory_region(obj);
>> +		i915_gem_object_init_memory_region(obj, mr);
>> +	}
> Perhaps a minor nit:
>
> Doing this after we have done the _get_pages() just doesn't seem right.
>
> I.e. we do work on the object, and then we init some portion of it.
>
> Do we need to do this incase the migration/placement fails?  If so,
> maybe a comment to that effect?

This is simply switching memory region under the lock, and to also move 
to another memory region list. Is it the naming _release_ and _init_ 
that is confusing?

/Thomas


>
> Thanks,
>
> Mike
>
>> +	return 0;
>> +}
>> +
>> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>> 			       struct sg_table *st)
>> {
>> @@ -814,6 +848,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,
>> +	.migrate = i915_ttm_migrate,
>> 	.mmap_offset = i915_ttm_mmap_offset,
>> 	.mmap_ops = &vm_ops_ttm,
>> };
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> index 1070d3afdce7..f909aaa09d9c 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>> *data, struct drm_file *file)
>> 	i915_gem_object_put(obj);
>> 	return ret;
>> }
>> +
>> +/**
>> + * i915_gem_object_wait_migration - Sync an accelerated migration
>> operation
>> + * @obj: The migrating object.
>> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
>> + *
>> + * Wait for any pending async migration operation on the object,
>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>> + * (swapin, initial clearing) initiated.
>> + *
>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>> + */
>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>> +				   unsigned int flags)
>> +{
>> +	might_sleep();
>> +	/* NOP for now. */
>> +	return 0;
>> +}
>> --
>> 2.31.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 18:53     ` Ruhl, Michael J
@ 2021-06-28 19:14       ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:14 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew

On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
> > -----Original Message-----
> > From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
> > Of
> > Thomas Hellström
> > Sent: Monday, June 28, 2021 10:46 AM
> > To: intel-gfx@lists.freedesktop.org;   
> > dri-devel@lists.freedesktop.org
> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
> > Matthew
> > <matthew.auld@intel.com>
> > Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
> > selftest for the
> > gem object migrate functionality
> > 
> > From: Matthew Auld <matthew.auld@intel.com>
> > 
> > A selftest for the gem object migrate functionality. Slightly
> > adapted
> > from the original by Matthew to the new interface and new fill blit
> > code.
> > 
> > Co-developed-by: Thomas Hellström
> > <thomas.hellstrom@linux.intel.com>
> > Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > ---
> > drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
> > .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
> > ++++++++++++++++++
> > .../drm/i915/selftests/i915_live_selftests.h  |   1 +
> > 3 files changed, 239 insertions(+)
> > create mode 100644
> > drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > 
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > index 1c18be067b58..ff147fd59874 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
> > i915_gem_object_funcs = {
> > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> > #include "selftests/huge_gem_object.c"
> > #include "selftests/huge_pages.c"
> > +#include "selftests/i915_gem_migrate.c"
> > #include "selftests/i915_gem_object.c"
> > #include "selftests/i915_gem_coherency.c"
> > #endif
> > diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > new file mode 100644
> > index 000000000000..a437b66f64d9
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > @@ -0,0 +1,237 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020-2021 Intel Corporation
> > + */
> > +
> > +#include "gt/intel_migrate.h"
> > +
> > +static int igt_smem_create_migrate(void *arg)
> > +{
> > +       struct intel_gt *gt = arg;
> > +       struct drm_i915_private *i915 = gt->i915;
> > +       struct drm_i915_gem_object *obj;
> > +       struct i915_gem_ww_ctx ww;
> > +       int err = 0;
> > +
> > +       /* Switch object backing-store on create */
> > +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
> > +       if (IS_ERR(obj))
> > +               return PTR_ERR(obj);
> > +
> > +       for_i915_gem_ww(&ww, err, true) {
> > +               err = i915_gem_object_lock(obj, &ww);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM)) {
> > +                       err = -EINVAL;
> > +                       continue;
> > +               }
> > +
> > +               err = i915_gem_object_migrate(obj, &ww,
> > INTEL_REGION_SMEM);
> > +               if (err)
> > +                       continue;
> > +
> > +               err = i915_gem_object_pin_pages(obj);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (i915_gem_object_can_migrate(obj,
> > INTEL_REGION_LMEM))
> > +                       err = -EINVAL;
> > +
> > +               i915_gem_object_unpin_pages(obj);
> > +       }
> > +       i915_gem_object_put(obj);
> > +
> > +       return err;
> > +}
> > +
> > +static int igt_lmem_create_migrate(void *arg)
> > +{
> > +       struct intel_gt *gt = arg;
> > +       struct drm_i915_private *i915 = gt->i915;
> > +       struct drm_i915_gem_object *obj;
> > +       struct i915_gem_ww_ctx ww;
> > +       int err = 0;
> > +
> > +       /* Switch object backing-store on create */
> > +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> > +       if (IS_ERR(obj))
> > +               return PTR_ERR(obj);
> > +
> > +       for_i915_gem_ww(&ww, err, true) {
> > +               err = i915_gem_object_lock(obj, &ww);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_LMEM)) {
> > +                       err = -EINVAL;
> > +                       continue;
> > +               }
> > +
> > +               err = i915_gem_object_migrate(obj, &ww,
> > INTEL_REGION_LMEM);
> > +               if (err)
> > +                       continue;
> > +
> > +               err = i915_gem_object_pin_pages(obj);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM))
> > +                       err = -EINVAL;
> > +
> > +               i915_gem_object_unpin_pages(obj);
> > +       }
> > +       i915_gem_object_put(obj);
> > +
> > +       return err;
> > +}
> > +
> > +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
> > +                                 struct drm_i915_gem_object *obj)
> > +{
> > +       int err;
> > +
> > +       err = i915_gem_object_lock(obj, ww);
> > +       if (err)
> > +               return err;
> > +
> > +       err = i915_gem_object_wait(obj,
> > +                                  I915_WAIT_INTERRUPTIBLE |
> > +                                  I915_WAIT_PRIORITY |
> > +                                  I915_WAIT_ALL,
> > +                                  MAX_SCHEDULE_TIMEOUT);
> > +       if (err)
> > +               return err;
> > +
> > +       if (i915_gem_object_is_lmem(obj)) {
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM)) {
> 
> I don't see any  testing of the parameter num_allowed.
> 
> Is that done somewhere else?
> 
> Mike

That's a user-space submitted parameter only, dictating what region the
object is allowed in when bound to the GPU. It's not exercised in this
selftest.

Thanks,
Thomas



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 19:14       ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:14 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew

On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
> > -----Original Message-----
> > From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
> > Of
> > Thomas Hellström
> > Sent: Monday, June 28, 2021 10:46 AM
> > To: intel-gfx@lists.freedesktop.org;   
> > dri-devel@lists.freedesktop.org
> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
> > Matthew
> > <matthew.auld@intel.com>
> > Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
> > selftest for the
> > gem object migrate functionality
> > 
> > From: Matthew Auld <matthew.auld@intel.com>
> > 
> > A selftest for the gem object migrate functionality. Slightly
> > adapted
> > from the original by Matthew to the new interface and new fill blit
> > code.
> > 
> > Co-developed-by: Thomas Hellström
> > <thomas.hellstrom@linux.intel.com>
> > Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > ---
> > drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
> > .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
> > ++++++++++++++++++
> > .../drm/i915/selftests/i915_live_selftests.h  |   1 +
> > 3 files changed, 239 insertions(+)
> > create mode 100644
> > drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > 
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > index 1c18be067b58..ff147fd59874 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
> > i915_gem_object_funcs = {
> > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> > #include "selftests/huge_gem_object.c"
> > #include "selftests/huge_pages.c"
> > +#include "selftests/i915_gem_migrate.c"
> > #include "selftests/i915_gem_object.c"
> > #include "selftests/i915_gem_coherency.c"
> > #endif
> > diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > new file mode 100644
> > index 000000000000..a437b66f64d9
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
> > @@ -0,0 +1,237 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2020-2021 Intel Corporation
> > + */
> > +
> > +#include "gt/intel_migrate.h"
> > +
> > +static int igt_smem_create_migrate(void *arg)
> > +{
> > +       struct intel_gt *gt = arg;
> > +       struct drm_i915_private *i915 = gt->i915;
> > +       struct drm_i915_gem_object *obj;
> > +       struct i915_gem_ww_ctx ww;
> > +       int err = 0;
> > +
> > +       /* Switch object backing-store on create */
> > +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
> > +       if (IS_ERR(obj))
> > +               return PTR_ERR(obj);
> > +
> > +       for_i915_gem_ww(&ww, err, true) {
> > +               err = i915_gem_object_lock(obj, &ww);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM)) {
> > +                       err = -EINVAL;
> > +                       continue;
> > +               }
> > +
> > +               err = i915_gem_object_migrate(obj, &ww,
> > INTEL_REGION_SMEM);
> > +               if (err)
> > +                       continue;
> > +
> > +               err = i915_gem_object_pin_pages(obj);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (i915_gem_object_can_migrate(obj,
> > INTEL_REGION_LMEM))
> > +                       err = -EINVAL;
> > +
> > +               i915_gem_object_unpin_pages(obj);
> > +       }
> > +       i915_gem_object_put(obj);
> > +
> > +       return err;
> > +}
> > +
> > +static int igt_lmem_create_migrate(void *arg)
> > +{
> > +       struct intel_gt *gt = arg;
> > +       struct drm_i915_private *i915 = gt->i915;
> > +       struct drm_i915_gem_object *obj;
> > +       struct i915_gem_ww_ctx ww;
> > +       int err = 0;
> > +
> > +       /* Switch object backing-store on create */
> > +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> > +       if (IS_ERR(obj))
> > +               return PTR_ERR(obj);
> > +
> > +       for_i915_gem_ww(&ww, err, true) {
> > +               err = i915_gem_object_lock(obj, &ww);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_LMEM)) {
> > +                       err = -EINVAL;
> > +                       continue;
> > +               }
> > +
> > +               err = i915_gem_object_migrate(obj, &ww,
> > INTEL_REGION_LMEM);
> > +               if (err)
> > +                       continue;
> > +
> > +               err = i915_gem_object_pin_pages(obj);
> > +               if (err)
> > +                       continue;
> > +
> > +               if (i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM))
> > +                       err = -EINVAL;
> > +
> > +               i915_gem_object_unpin_pages(obj);
> > +       }
> > +       i915_gem_object_put(obj);
> > +
> > +       return err;
> > +}
> > +
> > +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
> > +                                 struct drm_i915_gem_object *obj)
> > +{
> > +       int err;
> > +
> > +       err = i915_gem_object_lock(obj, ww);
> > +       if (err)
> > +               return err;
> > +
> > +       err = i915_gem_object_wait(obj,
> > +                                  I915_WAIT_INTERRUPTIBLE |
> > +                                  I915_WAIT_PRIORITY |
> > +                                  I915_WAIT_ALL,
> > +                                  MAX_SCHEDULE_TIMEOUT);
> > +       if (err)
> > +               return err;
> > +
> > +       if (i915_gem_object_is_lmem(obj)) {
> > +               if (!i915_gem_object_can_migrate(obj,
> > INTEL_REGION_SMEM)) {
> 
> I don't see any  testing of the parameter num_allowed.
> 
> Is that done somewhere else?
> 
> Mike

That's a user-space submitted parameter only, dictating what region the
object is allowed in when bound to the GPU. It's not exercised in this
selftest.

Thanks,
Thomas


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 19:14       ` Thomas Hellström
@ 2021-06-28 19:27         ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:27 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:15 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>
>Subject: Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for
>the gem object migrate functionality
>
>On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
>> > -----Original Message-----
>> > From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
>> > Of
>> > Thomas Hellström
>> > Sent: Monday, June 28, 2021 10:46 AM
>> > To: intel-gfx@lists.freedesktop.org;
>> > dri-devel@lists.freedesktop.org
>> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>> > Matthew
>> > <matthew.auld@intel.com>
>> > Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
>> > selftest for the
>> > gem object migrate functionality
>> >
>> > From: Matthew Auld <matthew.auld@intel.com>
>> >
>> > A selftest for the gem object migrate functionality. Slightly
>> > adapted
>> > from the original by Matthew to the new interface and new fill blit
>> > code.
>> >
>> > Co-developed-by: Thomas Hellström
>> > <thomas.hellstrom@linux.intel.com>
>> > Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>> > ---
>> > drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>> > .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>> > ++++++++++++++++++
>> > .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>> > 3 files changed, 239 insertions(+)
>> > create mode 100644
>> > drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> >
>> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > index 1c18be067b58..ff147fd59874 100644
>> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>> > i915_gem_object_funcs = {
>> > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>> > #include "selftests/huge_gem_object.c"
>> > #include "selftests/huge_pages.c"
>> > +#include "selftests/i915_gem_migrate.c"
>> > #include "selftests/i915_gem_object.c"
>> > #include "selftests/i915_gem_coherency.c"
>> > #endif
>> > diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > new file mode 100644
>> > index 000000000000..a437b66f64d9
>> > --- /dev/null
>> > +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > @@ -0,0 +1,237 @@
>> > +// SPDX-License-Identifier: MIT
>> > +/*
>> > + * Copyright © 2020-2021 Intel Corporation
>> > + */
>> > +
>> > +#include "gt/intel_migrate.h"
>> > +
>> > +static int igt_smem_create_migrate(void *arg)
>> > +{
>> > +       struct intel_gt *gt = arg;
>> > +       struct drm_i915_private *i915 = gt->i915;
>> > +       struct drm_i915_gem_object *obj;
>> > +       struct i915_gem_ww_ctx ww;
>> > +       int err = 0;
>> > +
>> > +       /* Switch object backing-store on create */
>> > +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>> > +       if (IS_ERR(obj))
>> > +               return PTR_ERR(obj);
>> > +
>> > +       for_i915_gem_ww(&ww, err, true) {
>> > +               err = i915_gem_object_lock(obj, &ww);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM)) {
>> > +                       err = -EINVAL;
>> > +                       continue;
>> > +               }
>> > +
>> > +               err = i915_gem_object_migrate(obj, &ww,
>> > INTEL_REGION_SMEM);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               err = i915_gem_object_pin_pages(obj);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_LMEM))
>> > +                       err = -EINVAL;
>> > +
>> > +               i915_gem_object_unpin_pages(obj);
>> > +       }
>> > +       i915_gem_object_put(obj);
>> > +
>> > +       return err;
>> > +}
>> > +
>> > +static int igt_lmem_create_migrate(void *arg)
>> > +{
>> > +       struct intel_gt *gt = arg;
>> > +       struct drm_i915_private *i915 = gt->i915;
>> > +       struct drm_i915_gem_object *obj;
>> > +       struct i915_gem_ww_ctx ww;
>> > +       int err = 0;
>> > +
>> > +       /* Switch object backing-store on create */
>> > +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>> > +       if (IS_ERR(obj))
>> > +               return PTR_ERR(obj);
>> > +
>> > +       for_i915_gem_ww(&ww, err, true) {
>> > +               err = i915_gem_object_lock(obj, &ww);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_LMEM)) {
>> > +                       err = -EINVAL;
>> > +                       continue;
>> > +               }
>> > +
>> > +               err = i915_gem_object_migrate(obj, &ww,
>> > INTEL_REGION_LMEM);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               err = i915_gem_object_pin_pages(obj);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM))
>> > +                       err = -EINVAL;
>> > +
>> > +               i915_gem_object_unpin_pages(obj);
>> > +       }
>> > +       i915_gem_object_put(obj);
>> > +
>> > +       return err;
>> > +}
>> > +
>> > +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>> > +                                 struct drm_i915_gem_object *obj)
>> > +{
>> > +       int err;
>> > +
>> > +       err = i915_gem_object_lock(obj, ww);
>> > +       if (err)
>> > +               return err;
>> > +
>> > +       err = i915_gem_object_wait(obj,
>> > +                                  I915_WAIT_INTERRUPTIBLE |
>> > +                                  I915_WAIT_PRIORITY |
>> > +                                  I915_WAIT_ALL,
>> > +                                  MAX_SCHEDULE_TIMEOUT);
>> > +       if (err)
>> > +               return err;
>> > +
>> > +       if (i915_gem_object_is_lmem(obj)) {
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM)) {
>>
>> I don't see any  testing of the parameter num_allowed.
>>
>> Is that done somewhere else?
>>
>> Mike
>
>That's a user-space submitted parameter only, dictating what region the
>object is allowed in when bound to the GPU. It's not exercised in this
>selftest.

Got it.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

M

>Thanks,
>Thomas
>


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 19:27         ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:27 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:15 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>
>Subject: Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for
>the gem object migrate functionality
>
>On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
>> > -----Original Message-----
>> > From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
>> > Of
>> > Thomas Hellström
>> > Sent: Monday, June 28, 2021 10:46 AM
>> > To: intel-gfx@lists.freedesktop.org;
>> > dri-devel@lists.freedesktop.org
>> > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>> > Matthew
>> > <matthew.auld@intel.com>
>> > Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
>> > selftest for the
>> > gem object migrate functionality
>> >
>> > From: Matthew Auld <matthew.auld@intel.com>
>> >
>> > A selftest for the gem object migrate functionality. Slightly
>> > adapted
>> > from the original by Matthew to the new interface and new fill blit
>> > code.
>> >
>> > Co-developed-by: Thomas Hellström
>> > <thomas.hellstrom@linux.intel.com>
>> > Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>> > ---
>> > drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>> > .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>> > ++++++++++++++++++
>> > .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>> > 3 files changed, 239 insertions(+)
>> > create mode 100644
>> > drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> >
>> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > index 1c18be067b58..ff147fd59874 100644
>> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> > @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>> > i915_gem_object_funcs = {
>> > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>> > #include "selftests/huge_gem_object.c"
>> > #include "selftests/huge_pages.c"
>> > +#include "selftests/i915_gem_migrate.c"
>> > #include "selftests/i915_gem_object.c"
>> > #include "selftests/i915_gem_coherency.c"
>> > #endif
>> > diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > new file mode 100644
>> > index 000000000000..a437b66f64d9
>> > --- /dev/null
>> > +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>> > @@ -0,0 +1,237 @@
>> > +// SPDX-License-Identifier: MIT
>> > +/*
>> > + * Copyright © 2020-2021 Intel Corporation
>> > + */
>> > +
>> > +#include "gt/intel_migrate.h"
>> > +
>> > +static int igt_smem_create_migrate(void *arg)
>> > +{
>> > +       struct intel_gt *gt = arg;
>> > +       struct drm_i915_private *i915 = gt->i915;
>> > +       struct drm_i915_gem_object *obj;
>> > +       struct i915_gem_ww_ctx ww;
>> > +       int err = 0;
>> > +
>> > +       /* Switch object backing-store on create */
>> > +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>> > +       if (IS_ERR(obj))
>> > +               return PTR_ERR(obj);
>> > +
>> > +       for_i915_gem_ww(&ww, err, true) {
>> > +               err = i915_gem_object_lock(obj, &ww);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM)) {
>> > +                       err = -EINVAL;
>> > +                       continue;
>> > +               }
>> > +
>> > +               err = i915_gem_object_migrate(obj, &ww,
>> > INTEL_REGION_SMEM);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               err = i915_gem_object_pin_pages(obj);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_LMEM))
>> > +                       err = -EINVAL;
>> > +
>> > +               i915_gem_object_unpin_pages(obj);
>> > +       }
>> > +       i915_gem_object_put(obj);
>> > +
>> > +       return err;
>> > +}
>> > +
>> > +static int igt_lmem_create_migrate(void *arg)
>> > +{
>> > +       struct intel_gt *gt = arg;
>> > +       struct drm_i915_private *i915 = gt->i915;
>> > +       struct drm_i915_gem_object *obj;
>> > +       struct i915_gem_ww_ctx ww;
>> > +       int err = 0;
>> > +
>> > +       /* Switch object backing-store on create */
>> > +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>> > +       if (IS_ERR(obj))
>> > +               return PTR_ERR(obj);
>> > +
>> > +       for_i915_gem_ww(&ww, err, true) {
>> > +               err = i915_gem_object_lock(obj, &ww);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_LMEM)) {
>> > +                       err = -EINVAL;
>> > +                       continue;
>> > +               }
>> > +
>> > +               err = i915_gem_object_migrate(obj, &ww,
>> > INTEL_REGION_LMEM);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               err = i915_gem_object_pin_pages(obj);
>> > +               if (err)
>> > +                       continue;
>> > +
>> > +               if (i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM))
>> > +                       err = -EINVAL;
>> > +
>> > +               i915_gem_object_unpin_pages(obj);
>> > +       }
>> > +       i915_gem_object_put(obj);
>> > +
>> > +       return err;
>> > +}
>> > +
>> > +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>> > +                                 struct drm_i915_gem_object *obj)
>> > +{
>> > +       int err;
>> > +
>> > +       err = i915_gem_object_lock(obj, ww);
>> > +       if (err)
>> > +               return err;
>> > +
>> > +       err = i915_gem_object_wait(obj,
>> > +                                  I915_WAIT_INTERRUPTIBLE |
>> > +                                  I915_WAIT_PRIORITY |
>> > +                                  I915_WAIT_ALL,
>> > +                                  MAX_SCHEDULE_TIMEOUT);
>> > +       if (err)
>> > +               return err;
>> > +
>> > +       if (i915_gem_object_is_lmem(obj)) {
>> > +               if (!i915_gem_object_can_migrate(obj,
>> > INTEL_REGION_SMEM)) {
>>
>> I don't see any  testing of the parameter num_allowed.
>>
>> Is that done somewhere else?
>>
>> Mike
>
>That's a user-space submitted parameter only, dictating what region the
>object is allowed in when bound to the GPU. It's not exercised in this
>selftest.

Got it.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

M

>Thanks,
>Thomas
>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
  2021-06-28 19:27         ` Ruhl, Michael J
@ 2021-06-28 19:32           ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:32 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 9:27 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Sent: Monday, June 28, 2021 3:15 PM
>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Auld, Matthew <matthew.auld@intel.com>
>> Subject: Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for
>> the gem object migrate functionality
>>
>> On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
>>>> -----Original Message-----
>>>> From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
>>>> Of
>>>> Thomas Hellström
>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>> To: intel-gfx@lists.freedesktop.org;
>>>> dri-devel@lists.freedesktop.org
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>>>> Matthew
>>>> <matthew.auld@intel.com>
>>>> Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
>>>> selftest for the
>>>> gem object migrate functionality
>>>>
>>>> From: Matthew Auld <matthew.auld@intel.com>
>>>>
>>>> A selftest for the gem object migrate functionality. Slightly
>>>> adapted
>>>> from the original by Matthew to the new interface and new fill blit
>>>> code.
>>>>
>>>> Co-developed-by: Thomas Hellström
>>>> <thomas.hellstrom@linux.intel.com>
>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>>>> ---
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>>>> .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>>>> ++++++++++++++++++
>>>> .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>>>> 3 files changed, 239 insertions(+)
>>>> create mode 100644
>>>> drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index 1c18be067b58..ff147fd59874 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>>>> i915_gem_object_funcs = {
>>>> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>>>> #include "selftests/huge_gem_object.c"
>>>> #include "selftests/huge_pages.c"
>>>> +#include "selftests/i915_gem_migrate.c"
>>>> #include "selftests/i915_gem_object.c"
>>>> #include "selftests/i915_gem_coherency.c"
>>>> #endif
>>>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> new file mode 100644
>>>> index 000000000000..a437b66f64d9
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> @@ -0,0 +1,237 @@
>>>> +// SPDX-License-Identifier: MIT
>>>> +/*
>>>> + * Copyright © 2020-2021 Intel Corporation
>>>> + */
>>>> +
>>>> +#include "gt/intel_migrate.h"
>>>> +
>>>> +static int igt_smem_create_migrate(void *arg)
>>>> +{
>>>> +       struct intel_gt *gt = arg;
>>>> +       struct drm_i915_private *i915 = gt->i915;
>>>> +       struct drm_i915_gem_object *obj;
>>>> +       struct i915_gem_ww_ctx ww;
>>>> +       int err = 0;
>>>> +
>>>> +       /* Switch object backing-store on create */
>>>> +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>>>> +       if (IS_ERR(obj))
>>>> +               return PTR_ERR(obj);
>>>> +
>>>> +       for_i915_gem_ww(&ww, err, true) {
>>>> +               err = i915_gem_object_lock(obj, &ww);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM)) {
>>>> +                       err = -EINVAL;
>>>> +                       continue;
>>>> +               }
>>>> +
>>>> +               err = i915_gem_object_migrate(obj, &ww,
>>>> INTEL_REGION_SMEM);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               err = i915_gem_object_pin_pages(obj);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_LMEM))
>>>> +                       err = -EINVAL;
>>>> +
>>>> +               i915_gem_object_unpin_pages(obj);
>>>> +       }
>>>> +       i915_gem_object_put(obj);
>>>> +
>>>> +       return err;
>>>> +}
>>>> +
>>>> +static int igt_lmem_create_migrate(void *arg)
>>>> +{
>>>> +       struct intel_gt *gt = arg;
>>>> +       struct drm_i915_private *i915 = gt->i915;
>>>> +       struct drm_i915_gem_object *obj;
>>>> +       struct i915_gem_ww_ctx ww;
>>>> +       int err = 0;
>>>> +
>>>> +       /* Switch object backing-store on create */
>>>> +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>>>> +       if (IS_ERR(obj))
>>>> +               return PTR_ERR(obj);
>>>> +
>>>> +       for_i915_gem_ww(&ww, err, true) {
>>>> +               err = i915_gem_object_lock(obj, &ww);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_LMEM)) {
>>>> +                       err = -EINVAL;
>>>> +                       continue;
>>>> +               }
>>>> +
>>>> +               err = i915_gem_object_migrate(obj, &ww,
>>>> INTEL_REGION_LMEM);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               err = i915_gem_object_pin_pages(obj);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM))
>>>> +                       err = -EINVAL;
>>>> +
>>>> +               i915_gem_object_unpin_pages(obj);
>>>> +       }
>>>> +       i915_gem_object_put(obj);
>>>> +
>>>> +       return err;
>>>> +}
>>>> +
>>>> +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>>>> +                                 struct drm_i915_gem_object *obj)
>>>> +{
>>>> +       int err;
>>>> +
>>>> +       err = i915_gem_object_lock(obj, ww);
>>>> +       if (err)
>>>> +               return err;
>>>> +
>>>> +       err = i915_gem_object_wait(obj,
>>>> +                                  I915_WAIT_INTERRUPTIBLE |
>>>> +                                  I915_WAIT_PRIORITY |
>>>> +                                  I915_WAIT_ALL,
>>>> +                                  MAX_SCHEDULE_TIMEOUT);
>>>> +       if (err)
>>>> +               return err;
>>>> +
>>>> +       if (i915_gem_object_is_lmem(obj)) {
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM)) {
>>> I don't see any  testing of the parameter num_allowed.
>>>
>>> Is that done somewhere else?
>>>
>>> Mike
>> That's a user-space submitted parameter only, dictating what region the
>> object is allowed in when bound to the GPU. It's not exercised in this
>> selftest.
> Got it.
>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>
> M

Thanks!

Thomas


>> Thanks,
>> Thomas
>>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality
@ 2021-06-28 19:32           ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:32 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 9:27 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Sent: Monday, June 28, 2021 3:15 PM
>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Auld, Matthew <matthew.auld@intel.com>
>> Subject: Re: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for
>> the gem object migrate functionality
>>
>> On Mon, 2021-06-28 at 18:53 +0000, Ruhl, Michael J wrote:
>>>> -----Original Message-----
>>>> From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf
>>>> Of
>>>> Thomas Hellström
>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>> To: intel-gfx@lists.freedesktop.org;
>>>> dri-devel@lists.freedesktop.org
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>>>> Matthew
>>>> <matthew.auld@intel.com>
>>>> Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/gem: Introduce a
>>>> selftest for the
>>>> gem object migrate functionality
>>>>
>>>> From: Matthew Auld <matthew.auld@intel.com>
>>>>
>>>> A selftest for the gem object migrate functionality. Slightly
>>>> adapted
>>>> from the original by Matthew to the new interface and new fill blit
>>>> code.
>>>>
>>>> Co-developed-by: Thomas Hellström
>>>> <thomas.hellstrom@linux.intel.com>
>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>>>> ---
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    |   1 +
>>>> .../drm/i915/gem/selftests/i915_gem_migrate.c | 237
>>>> ++++++++++++++++++
>>>> .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>>>> 3 files changed, 239 insertions(+)
>>>> create mode 100644
>>>> drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index 1c18be067b58..ff147fd59874 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -649,6 +649,7 @@ static const struct drm_gem_object_funcs
>>>> i915_gem_object_funcs = {
>>>> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>>>> #include "selftests/huge_gem_object.c"
>>>> #include "selftests/huge_pages.c"
>>>> +#include "selftests/i915_gem_migrate.c"
>>>> #include "selftests/i915_gem_object.c"
>>>> #include "selftests/i915_gem_coherency.c"
>>>> #endif
>>>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> new file mode 100644
>>>> index 000000000000..a437b66f64d9
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
>>>> @@ -0,0 +1,237 @@
>>>> +// SPDX-License-Identifier: MIT
>>>> +/*
>>>> + * Copyright © 2020-2021 Intel Corporation
>>>> + */
>>>> +
>>>> +#include "gt/intel_migrate.h"
>>>> +
>>>> +static int igt_smem_create_migrate(void *arg)
>>>> +{
>>>> +       struct intel_gt *gt = arg;
>>>> +       struct drm_i915_private *i915 = gt->i915;
>>>> +       struct drm_i915_gem_object *obj;
>>>> +       struct i915_gem_ww_ctx ww;
>>>> +       int err = 0;
>>>> +
>>>> +       /* Switch object backing-store on create */
>>>> +       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>>>> +       if (IS_ERR(obj))
>>>> +               return PTR_ERR(obj);
>>>> +
>>>> +       for_i915_gem_ww(&ww, err, true) {
>>>> +               err = i915_gem_object_lock(obj, &ww);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM)) {
>>>> +                       err = -EINVAL;
>>>> +                       continue;
>>>> +               }
>>>> +
>>>> +               err = i915_gem_object_migrate(obj, &ww,
>>>> INTEL_REGION_SMEM);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               err = i915_gem_object_pin_pages(obj);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_LMEM))
>>>> +                       err = -EINVAL;
>>>> +
>>>> +               i915_gem_object_unpin_pages(obj);
>>>> +       }
>>>> +       i915_gem_object_put(obj);
>>>> +
>>>> +       return err;
>>>> +}
>>>> +
>>>> +static int igt_lmem_create_migrate(void *arg)
>>>> +{
>>>> +       struct intel_gt *gt = arg;
>>>> +       struct drm_i915_private *i915 = gt->i915;
>>>> +       struct drm_i915_gem_object *obj;
>>>> +       struct i915_gem_ww_ctx ww;
>>>> +       int err = 0;
>>>> +
>>>> +       /* Switch object backing-store on create */
>>>> +       obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>>>> +       if (IS_ERR(obj))
>>>> +               return PTR_ERR(obj);
>>>> +
>>>> +       for_i915_gem_ww(&ww, err, true) {
>>>> +               err = i915_gem_object_lock(obj, &ww);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_LMEM)) {
>>>> +                       err = -EINVAL;
>>>> +                       continue;
>>>> +               }
>>>> +
>>>> +               err = i915_gem_object_migrate(obj, &ww,
>>>> INTEL_REGION_LMEM);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               err = i915_gem_object_pin_pages(obj);
>>>> +               if (err)
>>>> +                       continue;
>>>> +
>>>> +               if (i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM))
>>>> +                       err = -EINVAL;
>>>> +
>>>> +               i915_gem_object_unpin_pages(obj);
>>>> +       }
>>>> +       i915_gem_object_put(obj);
>>>> +
>>>> +       return err;
>>>> +}
>>>> +
>>>> +static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
>>>> +                                 struct drm_i915_gem_object *obj)
>>>> +{
>>>> +       int err;
>>>> +
>>>> +       err = i915_gem_object_lock(obj, ww);
>>>> +       if (err)
>>>> +               return err;
>>>> +
>>>> +       err = i915_gem_object_wait(obj,
>>>> +                                  I915_WAIT_INTERRUPTIBLE |
>>>> +                                  I915_WAIT_PRIORITY |
>>>> +                                  I915_WAIT_ALL,
>>>> +                                  MAX_SCHEDULE_TIMEOUT);
>>>> +       if (err)
>>>> +               return err;
>>>> +
>>>> +       if (i915_gem_object_is_lmem(obj)) {
>>>> +               if (!i915_gem_object_can_migrate(obj,
>>>> INTEL_REGION_SMEM)) {
>>> I don't see any  testing of the parameter num_allowed.
>>>
>>> Is that done somewhere else?
>>>
>>> Mike
>> That's a user-space submitted parameter only, dictating what region the
>> object is allowed in when bound to the GPU. It's not exercised in this
>> selftest.
> Got it.
>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>
> M

Thanks!

Thomas


>> Thanks,
>> Thomas
>>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 19:45     ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:45 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel
  Cc: Ruhl, Michael J, Auld, Matthew

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>;
>maarten.lankhorst@linux.intel.com; Thomas Hellström
><thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
><michael.j.ruhl@intel.com>
>Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
>dma-buf export
>
>If our exported dma-bufs are imported by another instance of our driver,
>that instance will typically have the imported dma-bufs locked during
>map_attachment(). But the exporter also locks the same reservation
>object in the map_dma_buf() callback, which leads to recursive locking.
>
>Add a live selftest to catch this case, and as a workaround until
>we fully support dynamic import and export, declare the exporter dynamic
>by providing NOP pin() and unpin() functions. This means our map_dma_buf()
>callback will *always* get called locked, and by pinning unconditionally
>in i915_gem_map_dma_buf() we make sure we don't need to use the
>move_notify() functionality which is not yet implemented.

An interesting abuse of the interface, but it seems reasonable (for now) to me.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
>Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
> .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
>++++++++++++++++++-
> 2 files changed, 108 insertions(+), 4 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>index 616c3a2f1baf..1d1eeb167d28 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>@@ -12,6 +12,8 @@
> #include "i915_gem_object.h"
> #include "i915_scatterlist.h"
>
>+I915_SELFTEST_DECLARE(static bool force_different_devices;)
>+
> static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
> {
> 	return to_intel_bo(buf->priv);
>@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>dma_buf_attachment *attachme
> 	struct scatterlist *src, *dst;
> 	int ret, i;
>
>-	ret = i915_gem_object_pin_pages_unlocked(obj);
>+	assert_object_held(obj);
>+
>+	ret = i915_gem_object_pin_pages(obj);
> 	if (ret)
> 		goto err;
>
>@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
>*dma_buf, enum dma_data_direct
> 	return err;
> }
>
>+/*
>+ * As a workaround until we fully support dynamic import and export,
>+ * declare the exporter dynamic by providing NOP pin() and unpin()
>functions.
>+ * This means our i915_gem_map_dma_buf() callback will *always* get
>called
>+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
>make
>+ * sure we don't need to use the move_notify() functionality which is
>+ * not yet implemented. Typically for the same-driver-another-instance case,
>+ * i915_gem_map_dma_buf() will be called at importer attach time and the
>+ * mapped sg_list will be cached by the dma-buf core for the
>+ * duration of the attachment.
>+ */
>+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
>+{
>+	return 0;
>+}
>+
>+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
>+{
>+}
>+
> static const struct dma_buf_ops i915_dmabuf_ops =  {
> 	.map_dma_buf = i915_gem_map_dma_buf,
> 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
>@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
> 	.vunmap = i915_gem_dmabuf_vunmap,
> 	.begin_cpu_access = i915_gem_begin_cpu_access,
> 	.end_cpu_access = i915_gem_end_cpu_access,
>+	.pin = i915_gem_dmabuf_pin,
>+	.unpin = i915_gem_dmabuf_unpin,
> };
>
> struct dma_buf *i915_gem_prime_export(struct drm_gem_object
>*gem_obj, int flags)
>@@ -241,7 +267,8 @@ struct drm_gem_object
>*i915_gem_prime_import(struct drm_device *dev,
> 	if (dma_buf->ops == &i915_dmabuf_ops) {
> 		obj = dma_buf_to_obj(dma_buf);
> 		/* is it from our device? */
>-		if (obj->base.dev == dev) {
>+		if (obj->base.dev == dev &&
>+		    !I915_SELFTEST_ONLY(force_different_devices)) {
> 			/*
> 			 * Importing dmabuf exported from out own gem
>increases
> 			 * refcount on gem itself instead of f_count of
>dmabuf.
>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>index dd74bc09ec88..24735d6c12a2 100644
>--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
> static int igt_dmabuf_import_self(void *arg)
> {
> 	struct drm_i915_private *i915 = arg;
>-	struct drm_i915_gem_object *obj;
>+	struct drm_i915_gem_object *obj, *import_obj;
> 	struct drm_gem_object *import;
> 	struct dma_buf *dmabuf;
> 	int err;
>@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
> 		err = -EINVAL;
> 		goto out_import;
> 	}
>+	import_obj = to_intel_bo(import);
>+
>+	i915_gem_object_lock(import_obj, NULL);
>+	err = ____i915_gem_object_get_pages(import_obj);
>+	i915_gem_object_unlock(import_obj);
>+	if (err) {
>+		pr_err("Same object dma-buf get_pages failed!\n");
>+		goto out_import;
>+	}
>
> 	err = 0;
> out_import:
>-	i915_gem_object_put(to_intel_bo(import));
>+	i915_gem_object_put(import_obj);
>+out_dmabuf:
>+	dma_buf_put(dmabuf);
>+out:
>+	i915_gem_object_put(obj);
>+	return err;
>+}
>+
>+static int igt_dmabuf_import_same_driver(void *arg)
>+{
>+	struct drm_i915_private *i915 = arg;
>+	struct drm_i915_gem_object *obj, *import_obj;
>+	struct drm_gem_object *import;
>+	struct dma_buf *dmabuf;
>+	int err;
>+
>+	force_different_devices = true;
>+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	if (IS_ERR(obj))
>+		goto out_ret;
>+
>+	dmabuf = i915_gem_prime_export(&obj->base, 0);
>+	if (IS_ERR(dmabuf)) {
>+		pr_err("i915_gem_prime_export failed with err=%d\n",
>+		       (int)PTR_ERR(dmabuf));
>+		err = PTR_ERR(dmabuf);
>+		goto out;
>+	}
>+
>+	import = i915_gem_prime_import(&i915->drm, dmabuf);
>+	if (IS_ERR(import)) {
>+		pr_err("i915_gem_prime_import failed with err=%d\n",
>+		       (int)PTR_ERR(import));
>+		err = PTR_ERR(import);
>+		goto out_dmabuf;
>+	}
>+
>+	if (import == &obj->base) {
>+		pr_err("i915_gem_prime_import reused gem object!\n");
>+		err = -EINVAL;
>+		goto out_import;
>+	}
>+
>+	import_obj = to_intel_bo(import);
>+
>+	i915_gem_object_lock(import_obj, NULL);
>+	err = ____i915_gem_object_get_pages(import_obj);
>+	if (err) {
>+		pr_err("Different objects dma-buf get_pages failed!\n");
>+		i915_gem_object_unlock(import_obj);
>+		goto out_import;
>+	}
>+
>+	/*
>+	 * If the exported object is not in system memory, something
>+	 * weird is going on. TODO: When p2p is supported, this is no
>+	 * longer considered weird.
>+	 */
>+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
>+		pr_err("Exported dma-buf is not in system memory\n");
>+		err = -EINVAL;
>+	}
>+	i915_gem_object_unlock(import_obj);
>+
>+out_import:
>+	i915_gem_object_put(import_obj);
> out_dmabuf:
> 	dma_buf_put(dmabuf);
> out:
> 	i915_gem_object_put(obj);
>+out_ret:
>+	force_different_devices = false;
> 	return err;
> }
>
>@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
>drm_i915_private *i915)
> {
> 	static const struct i915_subtest tests[] = {
> 		SUBTEST(igt_dmabuf_export),
>+		SUBTEST(igt_dmabuf_import_same_driver),
> 	};
>
> 	return i915_subtests(tests, i915);
>--
>2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
@ 2021-06-28 19:45     ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:45 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>;
>maarten.lankhorst@linux.intel.com; Thomas Hellström
><thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
><michael.j.ruhl@intel.com>
>Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
>dma-buf export
>
>If our exported dma-bufs are imported by another instance of our driver,
>that instance will typically have the imported dma-bufs locked during
>map_attachment(). But the exporter also locks the same reservation
>object in the map_dma_buf() callback, which leads to recursive locking.
>
>Add a live selftest to catch this case, and as a workaround until
>we fully support dynamic import and export, declare the exporter dynamic
>by providing NOP pin() and unpin() functions. This means our map_dma_buf()
>callback will *always* get called locked, and by pinning unconditionally
>in i915_gem_map_dma_buf() we make sure we don't need to use the
>move_notify() functionality which is not yet implemented.

An interesting abuse of the interface, but it seems reasonable (for now) to me.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
>Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
> .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
>++++++++++++++++++-
> 2 files changed, 108 insertions(+), 4 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>index 616c3a2f1baf..1d1eeb167d28 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>@@ -12,6 +12,8 @@
> #include "i915_gem_object.h"
> #include "i915_scatterlist.h"
>
>+I915_SELFTEST_DECLARE(static bool force_different_devices;)
>+
> static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
> {
> 	return to_intel_bo(buf->priv);
>@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>dma_buf_attachment *attachme
> 	struct scatterlist *src, *dst;
> 	int ret, i;
>
>-	ret = i915_gem_object_pin_pages_unlocked(obj);
>+	assert_object_held(obj);
>+
>+	ret = i915_gem_object_pin_pages(obj);
> 	if (ret)
> 		goto err;
>
>@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
>*dma_buf, enum dma_data_direct
> 	return err;
> }
>
>+/*
>+ * As a workaround until we fully support dynamic import and export,
>+ * declare the exporter dynamic by providing NOP pin() and unpin()
>functions.
>+ * This means our i915_gem_map_dma_buf() callback will *always* get
>called
>+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
>make
>+ * sure we don't need to use the move_notify() functionality which is
>+ * not yet implemented. Typically for the same-driver-another-instance case,
>+ * i915_gem_map_dma_buf() will be called at importer attach time and the
>+ * mapped sg_list will be cached by the dma-buf core for the
>+ * duration of the attachment.
>+ */
>+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
>+{
>+	return 0;
>+}
>+
>+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
>+{
>+}
>+
> static const struct dma_buf_ops i915_dmabuf_ops =  {
> 	.map_dma_buf = i915_gem_map_dma_buf,
> 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
>@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
> 	.vunmap = i915_gem_dmabuf_vunmap,
> 	.begin_cpu_access = i915_gem_begin_cpu_access,
> 	.end_cpu_access = i915_gem_end_cpu_access,
>+	.pin = i915_gem_dmabuf_pin,
>+	.unpin = i915_gem_dmabuf_unpin,
> };
>
> struct dma_buf *i915_gem_prime_export(struct drm_gem_object
>*gem_obj, int flags)
>@@ -241,7 +267,8 @@ struct drm_gem_object
>*i915_gem_prime_import(struct drm_device *dev,
> 	if (dma_buf->ops == &i915_dmabuf_ops) {
> 		obj = dma_buf_to_obj(dma_buf);
> 		/* is it from our device? */
>-		if (obj->base.dev == dev) {
>+		if (obj->base.dev == dev &&
>+		    !I915_SELFTEST_ONLY(force_different_devices)) {
> 			/*
> 			 * Importing dmabuf exported from out own gem
>increases
> 			 * refcount on gem itself instead of f_count of
>dmabuf.
>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>index dd74bc09ec88..24735d6c12a2 100644
>--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
> static int igt_dmabuf_import_self(void *arg)
> {
> 	struct drm_i915_private *i915 = arg;
>-	struct drm_i915_gem_object *obj;
>+	struct drm_i915_gem_object *obj, *import_obj;
> 	struct drm_gem_object *import;
> 	struct dma_buf *dmabuf;
> 	int err;
>@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
> 		err = -EINVAL;
> 		goto out_import;
> 	}
>+	import_obj = to_intel_bo(import);
>+
>+	i915_gem_object_lock(import_obj, NULL);
>+	err = ____i915_gem_object_get_pages(import_obj);
>+	i915_gem_object_unlock(import_obj);
>+	if (err) {
>+		pr_err("Same object dma-buf get_pages failed!\n");
>+		goto out_import;
>+	}
>
> 	err = 0;
> out_import:
>-	i915_gem_object_put(to_intel_bo(import));
>+	i915_gem_object_put(import_obj);
>+out_dmabuf:
>+	dma_buf_put(dmabuf);
>+out:
>+	i915_gem_object_put(obj);
>+	return err;
>+}
>+
>+static int igt_dmabuf_import_same_driver(void *arg)
>+{
>+	struct drm_i915_private *i915 = arg;
>+	struct drm_i915_gem_object *obj, *import_obj;
>+	struct drm_gem_object *import;
>+	struct dma_buf *dmabuf;
>+	int err;
>+
>+	force_different_devices = true;
>+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	if (IS_ERR(obj))
>+		goto out_ret;
>+
>+	dmabuf = i915_gem_prime_export(&obj->base, 0);
>+	if (IS_ERR(dmabuf)) {
>+		pr_err("i915_gem_prime_export failed with err=%d\n",
>+		       (int)PTR_ERR(dmabuf));
>+		err = PTR_ERR(dmabuf);
>+		goto out;
>+	}
>+
>+	import = i915_gem_prime_import(&i915->drm, dmabuf);
>+	if (IS_ERR(import)) {
>+		pr_err("i915_gem_prime_import failed with err=%d\n",
>+		       (int)PTR_ERR(import));
>+		err = PTR_ERR(import);
>+		goto out_dmabuf;
>+	}
>+
>+	if (import == &obj->base) {
>+		pr_err("i915_gem_prime_import reused gem object!\n");
>+		err = -EINVAL;
>+		goto out_import;
>+	}
>+
>+	import_obj = to_intel_bo(import);
>+
>+	i915_gem_object_lock(import_obj, NULL);
>+	err = ____i915_gem_object_get_pages(import_obj);
>+	if (err) {
>+		pr_err("Different objects dma-buf get_pages failed!\n");
>+		i915_gem_object_unlock(import_obj);
>+		goto out_import;
>+	}
>+
>+	/*
>+	 * If the exported object is not in system memory, something
>+	 * weird is going on. TODO: When p2p is supported, this is no
>+	 * longer considered weird.
>+	 */
>+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
>+		pr_err("Exported dma-buf is not in system memory\n");
>+		err = -EINVAL;
>+	}
>+	i915_gem_object_unlock(import_obj);
>+
>+out_import:
>+	i915_gem_object_put(import_obj);
> out_dmabuf:
> 	dma_buf_put(dmabuf);
> out:
> 	i915_gem_object_put(obj);
>+out_ret:
>+	force_different_devices = false;
> 	return err;
> }
>
>@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
>drm_i915_private *i915)
> {
> 	static const struct i915_subtest tests[] = {
> 		SUBTEST(igt_dmabuf_export),
>+		SUBTEST(igt_dmabuf_import_same_driver),
> 	};
>
> 	return i915_subtests(tests, i915);
>--
>2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 19:45     ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:45 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>
>Subject: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map
>time
>
>Until we support p2p dma or as a complement to that, migrate data
>to system memory at dma-buf map time if possible.
>
>v2:
>- Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
>  selftest to migrate if we are LMEM capable.
>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
> drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>index 1d1eeb167d28..5207aa3af009 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>@@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>dma_buf_attachment *attachme
>
> 	assert_object_held(obj);
>
>-	ret = i915_gem_object_pin_pages(obj);
>+	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
>+		return ERR_PTR(-EOPNOTSUPP);
>+
>+	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
>+	if (!ret)
>+		ret = i915_gem_object_pin_pages(obj);
> 	if (ret)
> 		goto err;

With the caveats of the previous patches this looks good.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>index 24735d6c12a2..b6278dba98d0 100644
>--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>@@ -94,7 +94,9 @@ static int igt_dmabuf_import_same_driver(void *arg)
> 	int err;
>
> 	force_different_devices = true;
>-	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>+	if (IS_ERR(obj))
>+		obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> 	if (IS_ERR(obj))
> 		goto out_ret;
>
>--
>2.31.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
@ 2021-06-28 19:45     ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:45 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>Thomas Hellström
>Sent: Monday, June 28, 2021 10:46 AM
>To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
><matthew.auld@intel.com>
>Subject: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map
>time
>
>Until we support p2p dma or as a complement to that, migrate data
>to system memory at dma-buf map time if possible.
>
>v2:
>- Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
>  selftest to migrate if we are LMEM capable.
>
>Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>---
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
> drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>index 1d1eeb167d28..5207aa3af009 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>@@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>dma_buf_attachment *attachme
>
> 	assert_object_held(obj);
>
>-	ret = i915_gem_object_pin_pages(obj);
>+	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
>+		return ERR_PTR(-EOPNOTSUPP);
>+
>+	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
>+	if (!ret)
>+		ret = i915_gem_object_pin_pages(obj);
> 	if (ret)
> 		goto err;

With the caveats of the previous patches this looks good.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>index 24735d6c12a2..b6278dba98d0 100644
>--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>@@ -94,7 +94,9 @@ static int igt_dmabuf_import_same_driver(void *arg)
> 	int err;
>
> 	force_different_devices = true;
>-	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>+	obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, 0);
>+	if (IS_ERR(obj))
>+		obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> 	if (IS_ERR(obj))
> 		goto out_ret;
>
>--
>2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 19:02       ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 19:50         ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:50 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew, lkp

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:03 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>
>On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>>> Thomas Hellström
>>> Sent: Monday, June 28, 2021 10:46 AM
>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>Matthew
>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>
>>> Introduce an interface to migrate objects between regions.
>>> This is primarily intended to migrate objects to LMEM for display and
>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>> performance-based migration.
>>>
>>> v2:
>>> - Verify that the memory region given as an id really exists.
>>>   (Reported by Matthew Auld)
>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>> region
>>>   to handle also switching region lists. (Reported by Matthew Auld)
>>> v3:
>>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>>   the correct region, even if the object ops doesn't have a migrate()
>>>   callback.
>>> - Update typo in commit message.
>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>
>>> Reported-by: kernel test robot <lkp@intel.com>
>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> ---
>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>> +++++++++++++++++++
>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> index 07e8ff9a8aae..1c18be067b58 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>>> drm_i915_gem_object *obj)
>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>> }
>>>
>>> +/**
>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>migrated
>>> + *
>>> + * @obj: The object to migrate
>>> + * @id: The region intended to migrate to
>>> + *
>>> + * Check whether the object backend supports migration to the
>>> + * given region. Note that pinning may affect the ability to migrate.
>>> + *
>>> + * Return: true if migration is possible, false otherwise.
>>> + */
>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>> +				 enum intel_region_id id)
>>> +{
>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>> +	struct intel_memory_region *mr;
>>> +	unsigned int i;
>>> +
>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>> +
>>> +	mr = i915->mm.regions[id];
>>> +	if (!mr)
>>> +		return false;
>>> +
>>> +	if (obj->mm.region == mr)
>>> +		return true;
>>> +
>>> +	if (!i915_gem_object_evictable(obj))
>>> +		return false;
>>> +
>>> +	if (!obj->ops->migrate)
>>> +		return false;
>>> +
>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>> +		return true;
>>> +
>>> +	if (num_allowed == 0)
>>> +		return false;
>>> +
>>> +	for (i = 0; i < num_allowed; ++i) {
>>> +		if (mr == obj->mm.placements[i])
>>> +			return true;
>>> +	}
>> Hi Thomas,
>>
>> I am a little confused over the difference in checks between this function
>> and i915_gem_object_migrate().
>>
>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>> false?
>>
>> So that means that under certain circumstances, you could not have a mr?
>>
>> If that is the case, when?
>>
>> Would that be when the I915_BO_ALLOC_USER is set?
>>
>> If so, should there be a check for "non" user vs user?
>>
>> Or maybe document this function pointing out why there are differences
>> and why?
>
>Yes, I'll give it some more documentation. The basic idea is that the
>above function also could be
>used to validate user supplied data, whereas there might be cases where
>we want to use the gem_object_migrate() function and override the above.
>
>
>>
>>> +	return false;
>>> +}
>>> +
>>> +/**
>>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>>> + * @obj: The object to migrate.
>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>>> + * not be successful in evicting other objects to make room for this object.
>> Is the ww for future consideration?  (I don't see any use of it in the patch).
>
>Yes, but it will remain optional.
>
>
>>
>>> + * @id: The region id to migrate to.
>>> + *
>>> + * Attempt to migrate the object to the desired memory region. The
>>> + * object backend must support migration and the object may not be
>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>> + * be locked.
>>> + * On successful completion, the object will have pages pointing to
>>> + * memory in the new region, but an async migration task may not have
>>> + * completed yet, and to accomplish that,
>>> i915_gem_object_wait_migration()
>>> + * must be called.
>>> + *
>>> + * Return: 0 on success. Negative error code on failure. In particular may
>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>avoidance
>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>> + * -EBUSY if the object is pinned.
>>> + */
>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct i915_gem_ww_ctx *ww,
>>> +			    enum intel_region_id id)
>>> +{
>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>> +	struct intel_memory_region *mr;
>>> +
>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>> +	assert_object_held(obj);
>>> +
>>> +	mr = i915->mm.regions[id];
>>> +	GEM_BUG_ON(!mr);
>>> +
>>> +	if (obj->mm.region == mr)
>>> +		return 0;
>>> +
>>> +	if (!i915_gem_object_evictable(obj))
>>> +		return -EBUSY;
>>> +
>>> +	if (!obj->ops->migrate)
>>> +		return -EOPNOTSUPP;
>> Why aren't you using _can_migrate here?
>
>It's just in case we want to override. I'll add some more comments about
>this.
>
>>
>>> +	return obj->ops->migrate(obj, mr);
>>> +}
>>> +
>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>> {
>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> index ea3224a480c4..8cbd7a5334e2 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> @@ -17,6 +17,8 @@
>>> #include "i915_gem_ww.h"
>>> #include "i915_vma_types.h"
>>>
>>> +enum intel_region_id;
>>> +
>>> /*
>>>   * XXX: There is a prevalence of the assumption that we fit the
>>>   * object's page count inside a 32bit _signed_ variable. Let's document
>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>> drm_i915_gem_object *obj);
>>>
>>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>>> *obj);
>>>
>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct i915_gem_ww_ctx *ww,
>>> +			    enum intel_region_id id);
>>> +
>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>> +				 enum intel_region_id id);
>>> +
>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>> +				   unsigned int flags);
>>> +
>>> #ifdef CONFIG_MMU_NOTIFIER
>>> static inline bool
>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>> 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 441f913c87e6..ef3de2ae9723 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>> @@ -18,6 +18,7 @@
>>>
>>> struct drm_i915_gem_object;
>>> struct intel_fronbuffer;
>>> +struct intel_memory_region;
>>>
>>> /*
>>>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>> 	 * delayed_free - Override the default delayed free implementation
>>> 	 */
>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>> +
>>> +	/**
>>> +	 * migrate - Migrate object to a different region either for
>>> +	 * pinning or for as long as the object lock is held.
>>> +	 */
>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>> +		       struct intel_memory_region *mr);
>>> +
>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>
>>> 	const struct vm_operations_struct *mmap_ops;
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> index c39d982c4fa6..8f89185b6507 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>> 	return &i915_ttm_bo_driver;
>>> }
>>>
>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>> +				struct ttm_placement *placement)
>>> {
>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>> 	struct ttm_operation_ctx ctx = {
>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		.no_wait_gpu = false,
>>> 	};
>>> 	struct sg_table *st;
>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>> -	struct ttm_placement placement;
>>> 	int real_num_busy;
>>> 	int ret;
>>>
>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>> I915_TTM_MAX_PLACEMENTS);
>>> -
>>> -	/* Move to the requested placement. */
>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>> -
>>> 	/* First try only the requested placement. No eviction. */
>>> -	real_num_busy =
>>> fetch_and_zero(&placement.num_busy_placement);
>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>> +	real_num_busy = fetch_and_zero(&placement-
>>>> num_busy_placement);
>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>> 	if (ret) {
>>> 		ret = i915_ttm_err_to_gem(ret);
>>> 		/*
>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		 * If the initial attempt fails, allow all accepted placements,
>>> 		 * evicting if necessary.
>>> 		 */
>>> -		placement.num_busy_placement = real_num_busy;
>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>> +		placement->num_busy_placement = real_num_busy;
>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>> 		if (ret)
>>> 			return i915_ttm_err_to_gem(ret);
>>> 	}
>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		i915_ttm_adjust_gem_after_move(obj);
>>> 	}
>>>
>>> -	/* Object either has a page vector or is an iomem object */
>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>> -	if (IS_ERR(st))
>>> -		return PTR_ERR(st);
>>> +	if (!obj->mm.pages) {
>>> +		/* Object either has a page vector or is an iomem object */
>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>> ttm.cached_io_st;
>>> +		if (IS_ERR(st))
>>> +			return PTR_ERR(st);
>>>
>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>> +		__i915_gem_object_set_pages(obj, st,
>>> i915_sg_dma_sizes(st->sgl));
>>> +	}
>>>
>>> 	return ret;
>>> }
>>>
>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>> +{
>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>> +	struct ttm_placement placement;
>>> +
>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>> I915_TTM_MAX_PLACEMENTS);
>>> +
>>> +	/* Move to the requested placement. */
>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>> +
>>> +	return __i915_ttm_get_pages(obj, &placement);
>>> +}
>>> +
>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct intel_memory_region *mr)
>>> +{
>>> +	struct ttm_place requested;
>>> +	struct ttm_placement placement;
>>> +	int ret;
>>> +
>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>> +	placement.num_placement = 1;
>>> +	placement.num_busy_placement = 1;
>>> +	placement.placement = &requested;
>>> +	placement.busy_placement = &requested;
>>> +
>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	if (obj->mm.region != mr) {
>>> +		i915_gem_object_release_memory_region(obj);
>>> +		i915_gem_object_init_memory_region(obj, mr);
>>> +	}
>> Perhaps a minor nit:
>>
>> Doing this after we have done the _get_pages() just doesn't seem right.
>>
>> I.e. we do work on the object, and then we init some portion of it.
>>
>> Do we need to do this incase the migration/placement fails?  If so,
>> maybe a comment to that effect?
>
>This is simply switching memory region under the lock, and to also move
>to another memory region list. Is it the naming _release_ and _init_
>that is confusing?

Hmm, re-reading my question, I am wondering if I was unclear.

My "real" question was, can the release/init occur before the _get_pages()?

But looking at this some more, I can see answer is probably no.

I was going to suggest calling _init_ _set_, but when I looked at it, it was
doing init things as well as setting things

Maybe just a comment like:

/* Complete the migration by updating the memory region info. */
if (object->mm...)

?

M

>/Thomas
>
>
>>
>> Thanks,
>>
>> Mike
>>
>>> +	return 0;
>>> +}
>>> +
>>> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>>> 			       struct sg_table *st)
>>> {
>>> @@ -814,6 +848,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,
>>> +	.migrate = i915_ttm_migrate,
>>> 	.mmap_offset = i915_ttm_mmap_offset,
>>> 	.mmap_ops = &vm_ops_ttm,
>>> };
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> index 1070d3afdce7..f909aaa09d9c 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>>> *data, struct drm_file *file)
>>> 	i915_gem_object_put(obj);
>>> 	return ret;
>>> }
>>> +
>>> +/**
>>> + * i915_gem_object_wait_migration - Sync an accelerated migration
>>> operation
>>> + * @obj: The migrating object.
>>> + * @flags: waiting flags. Currently supports only
>I915_WAIT_INTERRUPTIBLE.
>>> + *
>>> + * Wait for any pending async migration operation on the object,
>>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>>> + * (swapin, initial clearing) initiated.
>>> + *
>>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>>> + */
>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>> +				   unsigned int flags)
>>> +{
>>> +	might_sleep();
>>> +	/* NOP for now. */
>>> +	return 0;
>>> +}
>>> --
>>> 2.31.1

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 19:50         ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 19:50 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew

>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:03 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>
>On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>>> Thomas Hellström
>>> Sent: Monday, June 28, 2021 10:46 AM
>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>Matthew
>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>
>>> Introduce an interface to migrate objects between regions.
>>> This is primarily intended to migrate objects to LMEM for display and
>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>> performance-based migration.
>>>
>>> v2:
>>> - Verify that the memory region given as an id really exists.
>>>   (Reported by Matthew Auld)
>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>> region
>>>   to handle also switching region lists. (Reported by Matthew Auld)
>>> v3:
>>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>>   the correct region, even if the object ops doesn't have a migrate()
>>>   callback.
>>> - Update typo in commit message.
>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>
>>> Reported-by: kernel test robot <lkp@intel.com>
>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> ---
>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>> +++++++++++++++++++
>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> index 07e8ff9a8aae..1c18be067b58 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>>> drm_i915_gem_object *obj)
>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>> }
>>>
>>> +/**
>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>migrated
>>> + *
>>> + * @obj: The object to migrate
>>> + * @id: The region intended to migrate to
>>> + *
>>> + * Check whether the object backend supports migration to the
>>> + * given region. Note that pinning may affect the ability to migrate.
>>> + *
>>> + * Return: true if migration is possible, false otherwise.
>>> + */
>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>> +				 enum intel_region_id id)
>>> +{
>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>> +	struct intel_memory_region *mr;
>>> +	unsigned int i;
>>> +
>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>> +
>>> +	mr = i915->mm.regions[id];
>>> +	if (!mr)
>>> +		return false;
>>> +
>>> +	if (obj->mm.region == mr)
>>> +		return true;
>>> +
>>> +	if (!i915_gem_object_evictable(obj))
>>> +		return false;
>>> +
>>> +	if (!obj->ops->migrate)
>>> +		return false;
>>> +
>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>> +		return true;
>>> +
>>> +	if (num_allowed == 0)
>>> +		return false;
>>> +
>>> +	for (i = 0; i < num_allowed; ++i) {
>>> +		if (mr == obj->mm.placements[i])
>>> +			return true;
>>> +	}
>> Hi Thomas,
>>
>> I am a little confused over the difference in checks between this function
>> and i915_gem_object_migrate().
>>
>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>> false?
>>
>> So that means that under certain circumstances, you could not have a mr?
>>
>> If that is the case, when?
>>
>> Would that be when the I915_BO_ALLOC_USER is set?
>>
>> If so, should there be a check for "non" user vs user?
>>
>> Or maybe document this function pointing out why there are differences
>> and why?
>
>Yes, I'll give it some more documentation. The basic idea is that the
>above function also could be
>used to validate user supplied data, whereas there might be cases where
>we want to use the gem_object_migrate() function and override the above.
>
>
>>
>>> +	return false;
>>> +}
>>> +
>>> +/**
>>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>>> + * @obj: The object to migrate.
>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>>> + * not be successful in evicting other objects to make room for this object.
>> Is the ww for future consideration?  (I don't see any use of it in the patch).
>
>Yes, but it will remain optional.
>
>
>>
>>> + * @id: The region id to migrate to.
>>> + *
>>> + * Attempt to migrate the object to the desired memory region. The
>>> + * object backend must support migration and the object may not be
>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>> + * be locked.
>>> + * On successful completion, the object will have pages pointing to
>>> + * memory in the new region, but an async migration task may not have
>>> + * completed yet, and to accomplish that,
>>> i915_gem_object_wait_migration()
>>> + * must be called.
>>> + *
>>> + * Return: 0 on success. Negative error code on failure. In particular may
>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>avoidance
>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>> + * -EBUSY if the object is pinned.
>>> + */
>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct i915_gem_ww_ctx *ww,
>>> +			    enum intel_region_id id)
>>> +{
>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>> +	struct intel_memory_region *mr;
>>> +
>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>> +	assert_object_held(obj);
>>> +
>>> +	mr = i915->mm.regions[id];
>>> +	GEM_BUG_ON(!mr);
>>> +
>>> +	if (obj->mm.region == mr)
>>> +		return 0;
>>> +
>>> +	if (!i915_gem_object_evictable(obj))
>>> +		return -EBUSY;
>>> +
>>> +	if (!obj->ops->migrate)
>>> +		return -EOPNOTSUPP;
>> Why aren't you using _can_migrate here?
>
>It's just in case we want to override. I'll add some more comments about
>this.
>
>>
>>> +	return obj->ops->migrate(obj, mr);
>>> +}
>>> +
>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>> {
>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> index ea3224a480c4..8cbd7a5334e2 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>> @@ -17,6 +17,8 @@
>>> #include "i915_gem_ww.h"
>>> #include "i915_vma_types.h"
>>>
>>> +enum intel_region_id;
>>> +
>>> /*
>>>   * XXX: There is a prevalence of the assumption that we fit the
>>>   * object's page count inside a 32bit _signed_ variable. Let's document
>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>> drm_i915_gem_object *obj);
>>>
>>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>>> *obj);
>>>
>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct i915_gem_ww_ctx *ww,
>>> +			    enum intel_region_id id);
>>> +
>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>> +				 enum intel_region_id id);
>>> +
>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>> +				   unsigned int flags);
>>> +
>>> #ifdef CONFIG_MMU_NOTIFIER
>>> static inline bool
>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>> 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 441f913c87e6..ef3de2ae9723 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>> @@ -18,6 +18,7 @@
>>>
>>> struct drm_i915_gem_object;
>>> struct intel_fronbuffer;
>>> +struct intel_memory_region;
>>>
>>> /*
>>>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>> 	 * delayed_free - Override the default delayed free implementation
>>> 	 */
>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>> +
>>> +	/**
>>> +	 * migrate - Migrate object to a different region either for
>>> +	 * pinning or for as long as the object lock is held.
>>> +	 */
>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>> +		       struct intel_memory_region *mr);
>>> +
>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>
>>> 	const struct vm_operations_struct *mmap_ops;
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> index c39d982c4fa6..8f89185b6507 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>> 	return &i915_ttm_bo_driver;
>>> }
>>>
>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>> +				struct ttm_placement *placement)
>>> {
>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>> 	struct ttm_operation_ctx ctx = {
>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		.no_wait_gpu = false,
>>> 	};
>>> 	struct sg_table *st;
>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>> -	struct ttm_placement placement;
>>> 	int real_num_busy;
>>> 	int ret;
>>>
>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>> I915_TTM_MAX_PLACEMENTS);
>>> -
>>> -	/* Move to the requested placement. */
>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>> -
>>> 	/* First try only the requested placement. No eviction. */
>>> -	real_num_busy =
>>> fetch_and_zero(&placement.num_busy_placement);
>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>> +	real_num_busy = fetch_and_zero(&placement-
>>>> num_busy_placement);
>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>> 	if (ret) {
>>> 		ret = i915_ttm_err_to_gem(ret);
>>> 		/*
>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		 * If the initial attempt fails, allow all accepted placements,
>>> 		 * evicting if necessary.
>>> 		 */
>>> -		placement.num_busy_placement = real_num_busy;
>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>> +		placement->num_busy_placement = real_num_busy;
>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>> 		if (ret)
>>> 			return i915_ttm_err_to_gem(ret);
>>> 	}
>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>> drm_i915_gem_object *obj)
>>> 		i915_ttm_adjust_gem_after_move(obj);
>>> 	}
>>>
>>> -	/* Object either has a page vector or is an iomem object */
>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>> -	if (IS_ERR(st))
>>> -		return PTR_ERR(st);
>>> +	if (!obj->mm.pages) {
>>> +		/* Object either has a page vector or is an iomem object */
>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>> ttm.cached_io_st;
>>> +		if (IS_ERR(st))
>>> +			return PTR_ERR(st);
>>>
>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>> +		__i915_gem_object_set_pages(obj, st,
>>> i915_sg_dma_sizes(st->sgl));
>>> +	}
>>>
>>> 	return ret;
>>> }
>>>
>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>> +{
>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>> +	struct ttm_placement placement;
>>> +
>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>> I915_TTM_MAX_PLACEMENTS);
>>> +
>>> +	/* Move to the requested placement. */
>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>> +
>>> +	return __i915_ttm_get_pages(obj, &placement);
>>> +}
>>> +
>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>> +			    struct intel_memory_region *mr)
>>> +{
>>> +	struct ttm_place requested;
>>> +	struct ttm_placement placement;
>>> +	int ret;
>>> +
>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>> +	placement.num_placement = 1;
>>> +	placement.num_busy_placement = 1;
>>> +	placement.placement = &requested;
>>> +	placement.busy_placement = &requested;
>>> +
>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	if (obj->mm.region != mr) {
>>> +		i915_gem_object_release_memory_region(obj);
>>> +		i915_gem_object_init_memory_region(obj, mr);
>>> +	}
>> Perhaps a minor nit:
>>
>> Doing this after we have done the _get_pages() just doesn't seem right.
>>
>> I.e. we do work on the object, and then we init some portion of it.
>>
>> Do we need to do this incase the migration/placement fails?  If so,
>> maybe a comment to that effect?
>
>This is simply switching memory region under the lock, and to also move
>to another memory region list. Is it the naming _release_ and _init_
>that is confusing?

Hmm, re-reading my question, I am wondering if I was unclear.

My "real" question was, can the release/init occur before the _get_pages()?

But looking at this some more, I can see answer is probably no.

I was going to suggest calling _init_ _set_, but when I looked at it, it was
doing init things as well as setting things

Maybe just a comment like:

/* Complete the migration by updating the memory region info. */
if (object->mm...)

?

M

>/Thomas
>
>
>>
>> Thanks,
>>
>> Mike
>>
>>> +	return 0;
>>> +}
>>> +
>>> static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>>> 			       struct sg_table *st)
>>> {
>>> @@ -814,6 +848,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,
>>> +	.migrate = i915_ttm_migrate,
>>> 	.mmap_offset = i915_ttm_mmap_offset,
>>> 	.mmap_ops = &vm_ops_ttm,
>>> };
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> index 1070d3afdce7..f909aaa09d9c 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
>>> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void
>>> *data, struct drm_file *file)
>>> 	i915_gem_object_put(obj);
>>> 	return ret;
>>> }
>>> +
>>> +/**
>>> + * i915_gem_object_wait_migration - Sync an accelerated migration
>>> operation
>>> + * @obj: The migrating object.
>>> + * @flags: waiting flags. Currently supports only
>I915_WAIT_INTERRUPTIBLE.
>>> + *
>>> + * Wait for any pending async migration operation on the object,
>>> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
>>> + * (swapin, initial clearing) initiated.
>>> + *
>>> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
>>> + */
>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>> +				   unsigned int flags)
>>> +{
>>> +	might_sleep();
>>> +	/* NOP for now. */
>>> +	return 0;
>>> +}
>>> --
>>> 2.31.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
  2021-06-28 19:45     ` [Intel-gfx] " Ruhl, Michael J
@ 2021-06-28 19:51       ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:51 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 9:45 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>> Thomas Hellström
>> Sent: Monday, June 28, 2021 10:46 AM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
>> <matthew.auld@intel.com>
>> Subject: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map
>> time
>>
>> Until we support p2p dma or as a complement to that, migrate data
>> to system memory at dma-buf map time if possible.
>>
>> v2:
>> - Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
>>   selftest to migrate if we are LMEM capable.
>>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
>> drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
>> 2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> index 1d1eeb167d28..5207aa3af009 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> @@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>> dma_buf_attachment *attachme
>>
>> 	assert_object_held(obj);
>>
>> -	ret = i915_gem_object_pin_pages(obj);
>> +	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
>> +		return ERR_PTR(-EOPNOTSUPP);
>> +
>> +	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
>> +	if (!ret)
>> +		ret = i915_gem_object_pin_pages(obj);
>> 	if (ret)
>> 		goto err;
> With the caveats of the previous patches this looks good.
Yes, this sort of sucks, but knowing that we have a correct 
implementation in the works...
>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>
> Mike

Thanks for the reviews!

Thomas



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time
@ 2021-06-28 19:51       ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:51 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 9:45 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>> Thomas Hellström
>> Sent: Monday, June 28, 2021 10:46 AM
>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld, Matthew
>> <matthew.auld@intel.com>
>> Subject: [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map
>> time
>>
>> Until we support p2p dma or as a complement to that, migrate data
>> to system memory at dma-buf map time if possible.
>>
>> v2:
>> - Rebase on dynamic exporter. Update the igt_dmabuf_import_same_driver
>>   selftest to migrate if we are LMEM capable.
>>
>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c           | 7 ++++++-
>> drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 4 +++-
>> 2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> index 1d1eeb167d28..5207aa3af009 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>> @@ -29,7 +29,12 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>> dma_buf_attachment *attachme
>>
>> 	assert_object_held(obj);
>>
>> -	ret = i915_gem_object_pin_pages(obj);
>> +	if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
>> +		return ERR_PTR(-EOPNOTSUPP);
>> +
>> +	ret = i915_gem_object_migrate(obj, NULL, INTEL_REGION_SMEM);
>> +	if (!ret)
>> +		ret = i915_gem_object_pin_pages(obj);
>> 	if (ret)
>> 		goto err;
> With the caveats of the previous patches this looks good.
Yes, this sort of sucks, but knowing that we have a correct 
implementation in the works...
>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>
> Mike

Thanks for the reviews!

Thomas


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 19:50         ` [Intel-gfx] " Ruhl, Michael J
@ 2021-06-28 19:54           ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:54 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew, lkp


On 6/28/21 9:50 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Sent: Monday, June 28, 2021 3:03 PM
>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>> Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>
>>
>> On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>>> -----Original Message-----
>>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>>>> Thomas Hellström
>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>> Matthew
>>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>>
>>>> Introduce an interface to migrate objects between regions.
>>>> This is primarily intended to migrate objects to LMEM for display and
>>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>>> performance-based migration.
>>>>
>>>> v2:
>>>> - Verify that the memory region given as an id really exists.
>>>>    (Reported by Matthew Auld)
>>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>>> region
>>>>    to handle also switching region lists. (Reported by Matthew Auld)
>>>> v3:
>>>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>>>    the correct region, even if the object ops doesn't have a migrate()
>>>>    callback.
>>>> - Update typo in commit message.
>>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>>
>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> ---
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>>> +++++++++++++++++++
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index 07e8ff9a8aae..1c18be067b58 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>>>> drm_i915_gem_object *obj)
>>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>>> }
>>>>
>>>> +/**
>>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>> migrated
>>>> + *
>>>> + * @obj: The object to migrate
>>>> + * @id: The region intended to migrate to
>>>> + *
>>>> + * Check whether the object backend supports migration to the
>>>> + * given region. Note that pinning may affect the ability to migrate.
>>>> + *
>>>> + * Return: true if migration is possible, false otherwise.
>>>> + */
>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>>> +				 enum intel_region_id id)
>>>> +{
>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>>> +	struct intel_memory_region *mr;
>>>> +	unsigned int i;
>>>> +
>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>> +
>>>> +	mr = i915->mm.regions[id];
>>>> +	if (!mr)
>>>> +		return false;
>>>> +
>>>> +	if (obj->mm.region == mr)
>>>> +		return true;
>>>> +
>>>> +	if (!i915_gem_object_evictable(obj))
>>>> +		return false;
>>>> +
>>>> +	if (!obj->ops->migrate)
>>>> +		return false;
>>>> +
>>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>>> +		return true;
>>>> +
>>>> +	if (num_allowed == 0)
>>>> +		return false;
>>>> +
>>>> +	for (i = 0; i < num_allowed; ++i) {
>>>> +		if (mr == obj->mm.placements[i])
>>>> +			return true;
>>>> +	}
>>> Hi Thomas,
>>>
>>> I am a little confused over the difference in checks between this function
>>> and i915_gem_object_migrate().
>>>
>>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>>> false?
>>>
>>> So that means that under certain circumstances, you could not have a mr?
>>>
>>> If that is the case, when?
>>>
>>> Would that be when the I915_BO_ALLOC_USER is set?
>>>
>>> If so, should there be a check for "non" user vs user?
>>>
>>> Or maybe document this function pointing out why there are differences
>>> and why?
>> Yes, I'll give it some more documentation. The basic idea is that the
>> above function also could be
>> used to validate user supplied data, whereas there might be cases where
>> we want to use the gem_object_migrate() function and override the above.
>>
>>
>>>> +	return false;
>>>> +}
>>>> +
>>>> +/**
>>>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>>>> + * @obj: The object to migrate.
>>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>>>> + * not be successful in evicting other objects to make room for this object.
>>> Is the ww for future consideration?  (I don't see any use of it in the patch).
>> Yes, but it will remain optional.
>>
>>
>>>> + * @id: The region id to migrate to.
>>>> + *
>>>> + * Attempt to migrate the object to the desired memory region. The
>>>> + * object backend must support migration and the object may not be
>>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>>> + * be locked.
>>>> + * On successful completion, the object will have pages pointing to
>>>> + * memory in the new region, but an async migration task may not have
>>>> + * completed yet, and to accomplish that,
>>>> i915_gem_object_wait_migration()
>>>> + * must be called.
>>>> + *
>>>> + * Return: 0 on success. Negative error code on failure. In particular may
>>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>> avoidance
>>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>>> + * -EBUSY if the object is pinned.
>>>> + */
>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct i915_gem_ww_ctx *ww,
>>>> +			    enum intel_region_id id)
>>>> +{
>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>> +	struct intel_memory_region *mr;
>>>> +
>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>> +	assert_object_held(obj);
>>>> +
>>>> +	mr = i915->mm.regions[id];
>>>> +	GEM_BUG_ON(!mr);
>>>> +
>>>> +	if (obj->mm.region == mr)
>>>> +		return 0;
>>>> +
>>>> +	if (!i915_gem_object_evictable(obj))
>>>> +		return -EBUSY;
>>>> +
>>>> +	if (!obj->ops->migrate)
>>>> +		return -EOPNOTSUPP;
>>> Why aren't you using _can_migrate here?
>> It's just in case we want to override. I'll add some more comments about
>> this.
>>
>>>> +	return obj->ops->migrate(obj, mr);
>>>> +}
>>>> +
>>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>>> {
>>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> index ea3224a480c4..8cbd7a5334e2 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> @@ -17,6 +17,8 @@
>>>> #include "i915_gem_ww.h"
>>>> #include "i915_vma_types.h"
>>>>
>>>> +enum intel_region_id;
>>>> +
>>>> /*
>>>>    * XXX: There is a prevalence of the assumption that we fit the
>>>>    * object's page count inside a 32bit _signed_ variable. Let's document
>>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>>> drm_i915_gem_object *obj);
>>>>
>>>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>>>> *obj);
>>>>
>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct i915_gem_ww_ctx *ww,
>>>> +			    enum intel_region_id id);
>>>> +
>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>>> +				 enum intel_region_id id);
>>>> +
>>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>>> +				   unsigned int flags);
>>>> +
>>>> #ifdef CONFIG_MMU_NOTIFIER
>>>> static inline bool
>>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>>> 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 441f913c87e6..ef3de2ae9723 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>> @@ -18,6 +18,7 @@
>>>>
>>>> struct drm_i915_gem_object;
>>>> struct intel_fronbuffer;
>>>> +struct intel_memory_region;
>>>>
>>>> /*
>>>>    * struct i915_lut_handle tracks the fast lookups from handle to vma used
>>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>>> 	 * delayed_free - Override the default delayed free implementation
>>>> 	 */
>>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>>> +
>>>> +	/**
>>>> +	 * migrate - Migrate object to a different region either for
>>>> +	 * pinning or for as long as the object lock is held.
>>>> +	 */
>>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>>> +		       struct intel_memory_region *mr);
>>>> +
>>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>>
>>>> 	const struct vm_operations_struct *mmap_ops;
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> index c39d982c4fa6..8f89185b6507 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>>> 	return &i915_ttm_bo_driver;
>>>> }
>>>>
>>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>>> +				struct ttm_placement *placement)
>>>> {
>>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>>> 	struct ttm_operation_ctx ctx = {
>>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		.no_wait_gpu = false,
>>>> 	};
>>>> 	struct sg_table *st;
>>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>> -	struct ttm_placement placement;
>>>> 	int real_num_busy;
>>>> 	int ret;
>>>>
>>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>>> I915_TTM_MAX_PLACEMENTS);
>>>> -
>>>> -	/* Move to the requested placement. */
>>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>> -
>>>> 	/* First try only the requested placement. No eviction. */
>>>> -	real_num_busy =
>>>> fetch_and_zero(&placement.num_busy_placement);
>>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>>> +	real_num_busy = fetch_and_zero(&placement-
>>>>> num_busy_placement);
>>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>>> 	if (ret) {
>>>> 		ret = i915_ttm_err_to_gem(ret);
>>>> 		/*
>>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		 * If the initial attempt fails, allow all accepted placements,
>>>> 		 * evicting if necessary.
>>>> 		 */
>>>> -		placement.num_busy_placement = real_num_busy;
>>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>>> +		placement->num_busy_placement = real_num_busy;
>>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>>> 		if (ret)
>>>> 			return i915_ttm_err_to_gem(ret);
>>>> 	}
>>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		i915_ttm_adjust_gem_after_move(obj);
>>>> 	}
>>>>
>>>> -	/* Object either has a page vector or is an iomem object */
>>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>>> -	if (IS_ERR(st))
>>>> -		return PTR_ERR(st);
>>>> +	if (!obj->mm.pages) {
>>>> +		/* Object either has a page vector or is an iomem object */
>>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>>> ttm.cached_io_st;
>>>> +		if (IS_ERR(st))
>>>> +			return PTR_ERR(st);
>>>>
>>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>>> +		__i915_gem_object_set_pages(obj, st,
>>>> i915_sg_dma_sizes(st->sgl));
>>>> +	}
>>>>
>>>> 	return ret;
>>>> }
>>>>
>>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>> +{
>>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>> +	struct ttm_placement placement;
>>>> +
>>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>>> I915_TTM_MAX_PLACEMENTS);
>>>> +
>>>> +	/* Move to the requested placement. */
>>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>> +
>>>> +	return __i915_ttm_get_pages(obj, &placement);
>>>> +}
>>>> +
>>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct intel_memory_region *mr)
>>>> +{
>>>> +	struct ttm_place requested;
>>>> +	struct ttm_placement placement;
>>>> +	int ret;
>>>> +
>>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>>> +	placement.num_placement = 1;
>>>> +	placement.num_busy_placement = 1;
>>>> +	placement.placement = &requested;
>>>> +	placement.busy_placement = &requested;
>>>> +
>>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	if (obj->mm.region != mr) {
>>>> +		i915_gem_object_release_memory_region(obj);
>>>> +		i915_gem_object_init_memory_region(obj, mr);
>>>> +	}
>>> Perhaps a minor nit:
>>>
>>> Doing this after we have done the _get_pages() just doesn't seem right.
>>>
>>> I.e. we do work on the object, and then we init some portion of it.
>>>
>>> Do we need to do this incase the migration/placement fails?  If so,
>>> maybe a comment to that effect?
>> This is simply switching memory region under the lock, and to also move
>> to another memory region list. Is it the naming _release_ and _init_
>> that is confusing?
> Hmm, re-reading my question, I am wondering if I was unclear.
>
> My "real" question was, can the release/init occur before the _get_pages()?
>
> But looking at this some more, I can see answer is probably no.
>
> I was going to suggest calling _init_ _set_, but when I looked at it, it was
> doing init things as well as setting things
>
> Maybe just a comment like:
>
> /* Complete the migration by updating the memory region info. */
> if (object->mm...)

Sure, I'll add that. Note that another thread would have to take the 
object lock anyway to inspect both the region and the pages, so it 
shouldn't be confused by the order here.

/Thomas



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 19:54           ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-28 19:54 UTC (permalink / raw)
  To: Ruhl, Michael J, intel-gfx, dri-devel; +Cc: Auld, Matthew


On 6/28/21 9:50 PM, Ruhl, Michael J wrote:
>> -----Original Message-----
>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Sent: Monday, June 28, 2021 3:03 PM
>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>> Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>> Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>
>>
>> On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>>> -----Original Message-----
>>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
>>>> Thomas Hellström
>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>> Matthew
>>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>>
>>>> Introduce an interface to migrate objects between regions.
>>>> This is primarily intended to migrate objects to LMEM for display and
>>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>>> performance-based migration.
>>>>
>>>> v2:
>>>> - Verify that the memory region given as an id really exists.
>>>>    (Reported by Matthew Auld)
>>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>>> region
>>>>    to handle also switching region lists. (Reported by Matthew Auld)
>>>> v3:
>>>> - Fix i915_gem_object_can_migrate() to return true if object is already in
>>>>    the correct region, even if the object ops doesn't have a migrate()
>>>>    callback.
>>>> - Update typo in commit message.
>>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>>
>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> ---
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>>> +++++++++++++++++++
>>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index 07e8ff9a8aae..1c18be067b58 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct
>>>> drm_i915_gem_object *obj)
>>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>>> }
>>>>
>>>> +/**
>>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>> migrated
>>>> + *
>>>> + * @obj: The object to migrate
>>>> + * @id: The region intended to migrate to
>>>> + *
>>>> + * Check whether the object backend supports migration to the
>>>> + * given region. Note that pinning may affect the ability to migrate.
>>>> + *
>>>> + * Return: true if migration is possible, false otherwise.
>>>> + */
>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>>> +				 enum intel_region_id id)
>>>> +{
>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>>> +	struct intel_memory_region *mr;
>>>> +	unsigned int i;
>>>> +
>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>> +
>>>> +	mr = i915->mm.regions[id];
>>>> +	if (!mr)
>>>> +		return false;
>>>> +
>>>> +	if (obj->mm.region == mr)
>>>> +		return true;
>>>> +
>>>> +	if (!i915_gem_object_evictable(obj))
>>>> +		return false;
>>>> +
>>>> +	if (!obj->ops->migrate)
>>>> +		return false;
>>>> +
>>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>>> +		return true;
>>>> +
>>>> +	if (num_allowed == 0)
>>>> +		return false;
>>>> +
>>>> +	for (i = 0; i < num_allowed; ++i) {
>>>> +		if (mr == obj->mm.placements[i])
>>>> +			return true;
>>>> +	}
>>> Hi Thomas,
>>>
>>> I am a little confused over the difference in checks between this function
>>> and i915_gem_object_migrate().
>>>
>>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>>> false?
>>>
>>> So that means that under certain circumstances, you could not have a mr?
>>>
>>> If that is the case, when?
>>>
>>> Would that be when the I915_BO_ALLOC_USER is set?
>>>
>>> If so, should there be a check for "non" user vs user?
>>>
>>> Or maybe document this function pointing out why there are differences
>>> and why?
>> Yes, I'll give it some more documentation. The basic idea is that the
>> above function also could be
>> used to validate user supplied data, whereas there might be cases where
>> we want to use the gem_object_migrate() function and override the above.
>>
>>
>>>> +	return false;
>>>> +}
>>>> +
>>>> +/**
>>>> + * i915_gem_object_migrate - Migrate an object to the desired region id
>>>> + * @obj: The object to migrate.
>>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
>>>> + * not be successful in evicting other objects to make room for this object.
>>> Is the ww for future consideration?  (I don't see any use of it in the patch).
>> Yes, but it will remain optional.
>>
>>
>>>> + * @id: The region id to migrate to.
>>>> + *
>>>> + * Attempt to migrate the object to the desired memory region. The
>>>> + * object backend must support migration and the object may not be
>>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>>> + * be locked.
>>>> + * On successful completion, the object will have pages pointing to
>>>> + * memory in the new region, but an async migration task may not have
>>>> + * completed yet, and to accomplish that,
>>>> i915_gem_object_wait_migration()
>>>> + * must be called.
>>>> + *
>>>> + * Return: 0 on success. Negative error code on failure. In particular may
>>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>> avoidance
>>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>>> + * -EBUSY if the object is pinned.
>>>> + */
>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct i915_gem_ww_ctx *ww,
>>>> +			    enum intel_region_id id)
>>>> +{
>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>> +	struct intel_memory_region *mr;
>>>> +
>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>> +	assert_object_held(obj);
>>>> +
>>>> +	mr = i915->mm.regions[id];
>>>> +	GEM_BUG_ON(!mr);
>>>> +
>>>> +	if (obj->mm.region == mr)
>>>> +		return 0;
>>>> +
>>>> +	if (!i915_gem_object_evictable(obj))
>>>> +		return -EBUSY;
>>>> +
>>>> +	if (!obj->ops->migrate)
>>>> +		return -EOPNOTSUPP;
>>> Why aren't you using _can_migrate here?
>> It's just in case we want to override. I'll add some more comments about
>> this.
>>
>>>> +	return obj->ops->migrate(obj, mr);
>>>> +}
>>>> +
>>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>>> {
>>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> index ea3224a480c4..8cbd7a5334e2 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> @@ -17,6 +17,8 @@
>>>> #include "i915_gem_ww.h"
>>>> #include "i915_vma_types.h"
>>>>
>>>> +enum intel_region_id;
>>>> +
>>>> /*
>>>>    * XXX: There is a prevalence of the assumption that we fit the
>>>>    * object's page count inside a 32bit _signed_ variable. Let's document
>>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>>> drm_i915_gem_object *obj);
>>>>
>>>> bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object
>>>> *obj);
>>>>
>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct i915_gem_ww_ctx *ww,
>>>> +			    enum intel_region_id id);
>>>> +
>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
>>>> +				 enum intel_region_id id);
>>>> +
>>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
>>>> +				   unsigned int flags);
>>>> +
>>>> #ifdef CONFIG_MMU_NOTIFIER
>>>> static inline bool
>>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>>> 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 441f913c87e6..ef3de2ae9723 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>> @@ -18,6 +18,7 @@
>>>>
>>>> struct drm_i915_gem_object;
>>>> struct intel_fronbuffer;
>>>> +struct intel_memory_region;
>>>>
>>>> /*
>>>>    * struct i915_lut_handle tracks the fast lookups from handle to vma used
>>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>>> 	 * delayed_free - Override the default delayed free implementation
>>>> 	 */
>>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>>> +
>>>> +	/**
>>>> +	 * migrate - Migrate object to a different region either for
>>>> +	 * pinning or for as long as the object lock is held.
>>>> +	 */
>>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>>> +		       struct intel_memory_region *mr);
>>>> +
>>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>>
>>>> 	const struct vm_operations_struct *mmap_ops;
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> index c39d982c4fa6..8f89185b6507 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>>> 	return &i915_ttm_bo_driver;
>>>> }
>>>>
>>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>>> +				struct ttm_placement *placement)
>>>> {
>>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>>> 	struct ttm_operation_ctx ctx = {
>>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		.no_wait_gpu = false,
>>>> 	};
>>>> 	struct sg_table *st;
>>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>> -	struct ttm_placement placement;
>>>> 	int real_num_busy;
>>>> 	int ret;
>>>>
>>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>>> I915_TTM_MAX_PLACEMENTS);
>>>> -
>>>> -	/* Move to the requested placement. */
>>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>> -
>>>> 	/* First try only the requested placement. No eviction. */
>>>> -	real_num_busy =
>>>> fetch_and_zero(&placement.num_busy_placement);
>>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>>> +	real_num_busy = fetch_and_zero(&placement-
>>>>> num_busy_placement);
>>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>>> 	if (ret) {
>>>> 		ret = i915_ttm_err_to_gem(ret);
>>>> 		/*
>>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		 * If the initial attempt fails, allow all accepted placements,
>>>> 		 * evicting if necessary.
>>>> 		 */
>>>> -		placement.num_busy_placement = real_num_busy;
>>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>>> +		placement->num_busy_placement = real_num_busy;
>>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>>> 		if (ret)
>>>> 			return i915_ttm_err_to_gem(ret);
>>>> 	}
>>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>>> drm_i915_gem_object *obj)
>>>> 		i915_ttm_adjust_gem_after_move(obj);
>>>> 	}
>>>>
>>>> -	/* Object either has a page vector or is an iomem object */
>>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>>> -	if (IS_ERR(st))
>>>> -		return PTR_ERR(st);
>>>> +	if (!obj->mm.pages) {
>>>> +		/* Object either has a page vector or is an iomem object */
>>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>>> ttm.cached_io_st;
>>>> +		if (IS_ERR(st))
>>>> +			return PTR_ERR(st);
>>>>
>>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>>> +		__i915_gem_object_set_pages(obj, st,
>>>> i915_sg_dma_sizes(st->sgl));
>>>> +	}
>>>>
>>>> 	return ret;
>>>> }
>>>>
>>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>> +{
>>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>> +	struct ttm_placement placement;
>>>> +
>>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>>> I915_TTM_MAX_PLACEMENTS);
>>>> +
>>>> +	/* Move to the requested placement. */
>>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>> +
>>>> +	return __i915_ttm_get_pages(obj, &placement);
>>>> +}
>>>> +
>>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>>> +			    struct intel_memory_region *mr)
>>>> +{
>>>> +	struct ttm_place requested;
>>>> +	struct ttm_placement placement;
>>>> +	int ret;
>>>> +
>>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>>> +	placement.num_placement = 1;
>>>> +	placement.num_busy_placement = 1;
>>>> +	placement.placement = &requested;
>>>> +	placement.busy_placement = &requested;
>>>> +
>>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	if (obj->mm.region != mr) {
>>>> +		i915_gem_object_release_memory_region(obj);
>>>> +		i915_gem_object_init_memory_region(obj, mr);
>>>> +	}
>>> Perhaps a minor nit:
>>>
>>> Doing this after we have done the _get_pages() just doesn't seem right.
>>>
>>> I.e. we do work on the object, and then we init some portion of it.
>>>
>>> Do we need to do this incase the migration/placement fails?  If so,
>>> maybe a comment to that effect?
>> This is simply switching memory region under the lock, and to also move
>> to another memory region list. Is it the naming _release_ and _init_
>> that is confusing?
> Hmm, re-reading my question, I am wondering if I was unclear.
>
> My "real" question was, can the release/init occur before the _get_pages()?
>
> But looking at this some more, I can see answer is probably no.
>
> I was going to suggest calling _init_ _set_, but when I looked at it, it was
> doing init things as well as setting things
>
> Maybe just a comment like:
>
> /* Complete the migration by updating the memory region info. */
> if (object->mm...)

Sure, I'll add that. Note that another thread would have to take the 
object lock anyway to inspect both the region and the pages, so it 
shouldn't be confused by the order here.

/Thomas


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 19:54           ` [Intel-gfx] " Thomas Hellström
@ 2021-06-28 20:13             ` Ruhl, Michael J
  -1 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 20:13 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew, lkp



>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:54 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>
>On 6/28/21 9:50 PM, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> Sent: Monday, June 28, 2021 3:03 PM
>>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>> Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>
>>>
>>> On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>>>> -----Original Message-----
>>>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf
>Of
>>>>> Thomas Hellström
>>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>>> Matthew
>>>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>>>
>>>>> Introduce an interface to migrate objects between regions.
>>>>> This is primarily intended to migrate objects to LMEM for display and
>>>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>>>> performance-based migration.
>>>>>
>>>>> v2:
>>>>> - Verify that the memory region given as an id really exists.
>>>>>    (Reported by Matthew Auld)
>>>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>>>> region
>>>>>    to handle also switching region lists. (Reported by Matthew Auld)
>>>>> v3:
>>>>> - Fix i915_gem_object_can_migrate() to return true if object is already
>in
>>>>>    the correct region, even if the object ops doesn't have a migrate()
>>>>>    callback.
>>>>> - Update typo in commit message.
>>>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>>>
>>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>>> ---
>>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>>>> +++++++++++++++++++
>>>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> index 07e8ff9a8aae..1c18be067b58 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const
>struct
>>>>> drm_i915_gem_object *obj)
>>>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>>>> }
>>>>>
>>>>> +/**
>>>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>>> migrated
>>>>> + *
>>>>> + * @obj: The object to migrate
>>>>> + * @id: The region intended to migrate to
>>>>> + *
>>>>> + * Check whether the object backend supports migration to the
>>>>> + * given region. Note that pinning may affect the ability to migrate.
>>>>> + *
>>>>> + * Return: true if migration is possible, false otherwise.
>>>>> + */
>>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object
>*obj,
>>>>> +				 enum intel_region_id id)
>>>>> +{
>>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>>>> +	struct intel_memory_region *mr;
>>>>> +	unsigned int i;
>>>>> +
>>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>>> +
>>>>> +	mr = i915->mm.regions[id];
>>>>> +	if (!mr)
>>>>> +		return false;
>>>>> +
>>>>> +	if (obj->mm.region == mr)
>>>>> +		return true;
>>>>> +
>>>>> +	if (!i915_gem_object_evictable(obj))
>>>>> +		return false;
>>>>> +
>>>>> +	if (!obj->ops->migrate)
>>>>> +		return false;
>>>>> +
>>>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>>>> +		return true;
>>>>> +
>>>>> +	if (num_allowed == 0)
>>>>> +		return false;
>>>>> +
>>>>> +	for (i = 0; i < num_allowed; ++i) {
>>>>> +		if (mr == obj->mm.placements[i])
>>>>> +			return true;
>>>>> +	}
>>>> Hi Thomas,
>>>>
>>>> I am a little confused over the difference in checks between this function
>>>> and i915_gem_object_migrate().
>>>>
>>>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>>>> false?
>>>>
>>>> So that means that under certain circumstances, you could not have a mr?
>>>>
>>>> If that is the case, when?
>>>>
>>>> Would that be when the I915_BO_ALLOC_USER is set?
>>>>
>>>> If so, should there be a check for "non" user vs user?
>>>>
>>>> Or maybe document this function pointing out why there are differences
>>>> and why?
>>> Yes, I'll give it some more documentation. The basic idea is that the
>>> above function also could be
>>> used to validate user supplied data, whereas there might be cases where
>>> we want to use the gem_object_migrate() function and override the
>above.
>>>
>>>
>>>>> +	return false;
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * i915_gem_object_migrate - Migrate an object to the desired region
>id
>>>>> + * @obj: The object to migrate.
>>>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend
>may
>>>>> + * not be successful in evicting other objects to make room for this
>object.
>>>> Is the ww for future consideration?  (I don't see any use of it in the
>patch).
>>> Yes, but it will remain optional.
>>>
>>>
>>>>> + * @id: The region id to migrate to.
>>>>> + *
>>>>> + * Attempt to migrate the object to the desired memory region. The
>>>>> + * object backend must support migration and the object may not be
>>>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>>>> + * be locked.
>>>>> + * On successful completion, the object will have pages pointing to
>>>>> + * memory in the new region, but an async migration task may not
>have
>>>>> + * completed yet, and to accomplish that,
>>>>> i915_gem_object_wait_migration()
>>>>> + * must be called.
>>>>> + *
>>>>> + * Return: 0 on success. Negative error code on failure. In particular
>may
>>>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>>> avoidance
>>>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>>>> + * -EBUSY if the object is pinned.
>>>>> + */
>>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct i915_gem_ww_ctx *ww,
>>>>> +			    enum intel_region_id id)
>>>>> +{
>>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>>> +	struct intel_memory_region *mr;
>>>>> +
>>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>>> +	assert_object_held(obj);
>>>>> +
>>>>> +	mr = i915->mm.regions[id];
>>>>> +	GEM_BUG_ON(!mr);
>>>>> +
>>>>> +	if (obj->mm.region == mr)
>>>>> +		return 0;
>>>>> +
>>>>> +	if (!i915_gem_object_evictable(obj))
>>>>> +		return -EBUSY;
>>>>> +
>>>>> +	if (!obj->ops->migrate)
>>>>> +		return -EOPNOTSUPP;
>>>> Why aren't you using _can_migrate here?
>>> It's just in case we want to override. I'll add some more comments about
>>> this.
>>>
>>>>> +	return obj->ops->migrate(obj, mr);
>>>>> +}
>>>>> +
>>>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>>>> {
>>>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> index ea3224a480c4..8cbd7a5334e2 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> @@ -17,6 +17,8 @@
>>>>> #include "i915_gem_ww.h"
>>>>> #include "i915_vma_types.h"
>>>>>
>>>>> +enum intel_region_id;
>>>>> +
>>>>> /*
>>>>>    * XXX: There is a prevalence of the assumption that we fit the
>>>>>    * object's page count inside a 32bit _signed_ variable. Let's document
>>>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>>>> drm_i915_gem_object *obj);
>>>>>
>>>>> bool i915_gem_object_validates_to_lmem(struct
>drm_i915_gem_object
>>>>> *obj);
>>>>>
>>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct i915_gem_ww_ctx *ww,
>>>>> +			    enum intel_region_id id);
>>>>> +
>>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object
>*obj,
>>>>> +				 enum intel_region_id id);
>>>>> +
>>>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object
>*obj,
>>>>> +				   unsigned int flags);
>>>>> +
>>>>> #ifdef CONFIG_MMU_NOTIFIER
>>>>> static inline bool
>>>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>>>> 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 441f913c87e6..ef3de2ae9723 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>>> @@ -18,6 +18,7 @@
>>>>>
>>>>> struct drm_i915_gem_object;
>>>>> struct intel_fronbuffer;
>>>>> +struct intel_memory_region;
>>>>>
>>>>> /*
>>>>>    * struct i915_lut_handle tracks the fast lookups from handle to vma
>used
>>>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>>>> 	 * delayed_free - Override the default delayed free implementation
>>>>> 	 */
>>>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>>>> +
>>>>> +	/**
>>>>> +	 * migrate - Migrate object to a different region either for
>>>>> +	 * pinning or for as long as the object lock is held.
>>>>> +	 */
>>>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>>>> +		       struct intel_memory_region *mr);
>>>>> +
>>>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>>>
>>>>> 	const struct vm_operations_struct *mmap_ops;
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> index c39d982c4fa6..8f89185b6507 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>>>> 	return &i915_ttm_bo_driver;
>>>>> }
>>>>>
>>>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>>>> +				struct ttm_placement *placement)
>>>>> {
>>>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>>>> 	struct ttm_operation_ctx ctx = {
>>>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		.no_wait_gpu = false,
>>>>> 	};
>>>>> 	struct sg_table *st;
>>>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>>> -	struct ttm_placement placement;
>>>>> 	int real_num_busy;
>>>>> 	int ret;
>>>>>
>>>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>>>> I915_TTM_MAX_PLACEMENTS);
>>>>> -
>>>>> -	/* Move to the requested placement. */
>>>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>>> -
>>>>> 	/* First try only the requested placement. No eviction. */
>>>>> -	real_num_busy =
>>>>> fetch_and_zero(&placement.num_busy_placement);
>>>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>>>> +	real_num_busy = fetch_and_zero(&placement-
>>>>>> num_busy_placement);
>>>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>>>> 	if (ret) {
>>>>> 		ret = i915_ttm_err_to_gem(ret);
>>>>> 		/*
>>>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		 * If the initial attempt fails, allow all accepted placements,
>>>>> 		 * evicting if necessary.
>>>>> 		 */
>>>>> -		placement.num_busy_placement = real_num_busy;
>>>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>>>> +		placement->num_busy_placement = real_num_busy;
>>>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>>>> 		if (ret)
>>>>> 			return i915_ttm_err_to_gem(ret);
>>>>> 	}
>>>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		i915_ttm_adjust_gem_after_move(obj);
>>>>> 	}
>>>>>
>>>>> -	/* Object either has a page vector or is an iomem object */
>>>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>>>> -	if (IS_ERR(st))
>>>>> -		return PTR_ERR(st);
>>>>> +	if (!obj->mm.pages) {
>>>>> +		/* Object either has a page vector or is an iomem object */
>>>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>>>> ttm.cached_io_st;
>>>>> +		if (IS_ERR(st))
>>>>> +			return PTR_ERR(st);
>>>>>
>>>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>>>> +		__i915_gem_object_set_pages(obj, st,
>>>>> i915_sg_dma_sizes(st->sgl));
>>>>> +	}
>>>>>
>>>>> 	return ret;
>>>>> }
>>>>>
>>>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>>> +{
>>>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>>> +	struct ttm_placement placement;
>>>>> +
>>>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>>>> I915_TTM_MAX_PLACEMENTS);
>>>>> +
>>>>> +	/* Move to the requested placement. */
>>>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>>> +
>>>>> +	return __i915_ttm_get_pages(obj, &placement);
>>>>> +}
>>>>> +
>>>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct intel_memory_region *mr)
>>>>> +{
>>>>> +	struct ttm_place requested;
>>>>> +	struct ttm_placement placement;
>>>>> +	int ret;
>>>>> +
>>>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>>>> +	placement.num_placement = 1;
>>>>> +	placement.num_busy_placement = 1;
>>>>> +	placement.placement = &requested;
>>>>> +	placement.busy_placement = &requested;
>>>>> +
>>>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>>>> +	if (ret)
>>>>> +		return ret;
>>>>> +
>>>>> +	if (obj->mm.region != mr) {
>>>>> +		i915_gem_object_release_memory_region(obj);
>>>>> +		i915_gem_object_init_memory_region(obj, mr);
>>>>> +	}
>>>> Perhaps a minor nit:
>>>>
>>>> Doing this after we have done the _get_pages() just doesn't seem right.
>>>>
>>>> I.e. we do work on the object, and then we init some portion of it.
>>>>
>>>> Do we need to do this incase the migration/placement fails?  If so,
>>>> maybe a comment to that effect?
>>> This is simply switching memory region under the lock, and to also move
>>> to another memory region list. Is it the naming _release_ and _init_
>>> that is confusing?
>> Hmm, re-reading my question, I am wondering if I was unclear.
>>
>> My "real" question was, can the release/init occur before the _get_pages()?
>>
>> But looking at this some more, I can see answer is probably no.
>>
>> I was going to suggest calling _init_ _set_, but when I looked at it, it was
>> doing init things as well as setting things
>>
>> Maybe just a comment like:
>>
>> /* Complete the migration by updating the memory region info. */
>> if (object->mm...)
>
>Sure, I'll add that. Note that another thread would have to take the
>object lock anyway to inspect both the region and the pages, so it
>shouldn't be confused by the order here.

Understood.

I think I was just disoriented by the pattern. :)

With the added documentation, I think this looks good.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>/Thomas
>


^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-28 20:13             ` Ruhl, Michael J
  0 siblings, 0 replies; 54+ messages in thread
From: Ruhl, Michael J @ 2021-06-28 20:13 UTC (permalink / raw)
  To: Thomas Hellström, intel-gfx, dri-devel; +Cc: Auld, Matthew



>-----Original Message-----
>From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Sent: Monday, June 28, 2021 3:54 PM
>To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>
>
>On 6/28/21 9:50 PM, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> Sent: Monday, June 28, 2021 3:03 PM
>>> To: Ruhl, Michael J <michael.j.ruhl@intel.com>; intel-
>>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Auld, Matthew <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>> Subject: Re: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>
>>>
>>> On 6/28/21 8:11 PM, Ruhl, Michael J wrote:
>>>>> -----Original Message-----
>>>>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf
>Of
>>>>> Thomas Hellström
>>>>> Sent: Monday, June 28, 2021 10:46 AM
>>>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>; Auld,
>>> Matthew
>>>>> <matthew.auld@intel.com>; lkp <lkp@intel.com>
>>>>> Subject: [PATCH v3 1/5] drm/i915/gem: Implement object migration
>>>>>
>>>>> Introduce an interface to migrate objects between regions.
>>>>> This is primarily intended to migrate objects to LMEM for display and
>>>>> to SYSTEM for dma-buf, but might be reused in one form or another for
>>>>> performance-based migration.
>>>>>
>>>>> v2:
>>>>> - Verify that the memory region given as an id really exists.
>>>>>    (Reported by Matthew Auld)
>>>>> - Call i915_gem_object_{init,release}_memory_region() when switching
>>>>> region
>>>>>    to handle also switching region lists. (Reported by Matthew Auld)
>>>>> v3:
>>>>> - Fix i915_gem_object_can_migrate() to return true if object is already
>in
>>>>>    the correct region, even if the object ops doesn't have a migrate()
>>>>>    callback.
>>>>> - Update typo in commit message.
>>>>> - Fix kerneldoc of i915_gem_object_wait_migration().
>>>>>
>>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>>> ---
>>>>> drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96
>>>>> +++++++++++++++++++
>>>>> drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>>>>> .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>>>>> drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>>>>> drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>>>>> 5 files changed, 188 insertions(+), 17 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> index 07e8ff9a8aae..1c18be067b58 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>>> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const
>struct
>>>>> drm_i915_gem_object *obj)
>>>>> 	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>>>>> }
>>>>>
>>>>> +/**
>>>>> + * i915_gem_object_can_migrate - Whether an object likely can be
>>> migrated
>>>>> + *
>>>>> + * @obj: The object to migrate
>>>>> + * @id: The region intended to migrate to
>>>>> + *
>>>>> + * Check whether the object backend supports migration to the
>>>>> + * given region. Note that pinning may affect the ability to migrate.
>>>>> + *
>>>>> + * Return: true if migration is possible, false otherwise.
>>>>> + */
>>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object
>*obj,
>>>>> +				 enum intel_region_id id)
>>>>> +{
>>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>>> +	unsigned int num_allowed = obj->mm.n_placements;
>>>>> +	struct intel_memory_region *mr;
>>>>> +	unsigned int i;
>>>>> +
>>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>>> +
>>>>> +	mr = i915->mm.regions[id];
>>>>> +	if (!mr)
>>>>> +		return false;
>>>>> +
>>>>> +	if (obj->mm.region == mr)
>>>>> +		return true;
>>>>> +
>>>>> +	if (!i915_gem_object_evictable(obj))
>>>>> +		return false;
>>>>> +
>>>>> +	if (!obj->ops->migrate)
>>>>> +		return false;
>>>>> +
>>>>> +	if (!(obj->flags & I915_BO_ALLOC_USER))
>>>>> +		return true;
>>>>> +
>>>>> +	if (num_allowed == 0)
>>>>> +		return false;
>>>>> +
>>>>> +	for (i = 0; i < num_allowed; ++i) {
>>>>> +		if (mr == obj->mm.placements[i])
>>>>> +			return true;
>>>>> +	}
>>>> Hi Thomas,
>>>>
>>>> I am a little confused over the difference in checks between this function
>>>> and i915_gem_object_migrate().
>>>>
>>>> Why is the lack of an mr a BUG_ON in _object_migrate(), but here it just
>>>> false?
>>>>
>>>> So that means that under certain circumstances, you could not have a mr?
>>>>
>>>> If that is the case, when?
>>>>
>>>> Would that be when the I915_BO_ALLOC_USER is set?
>>>>
>>>> If so, should there be a check for "non" user vs user?
>>>>
>>>> Or maybe document this function pointing out why there are differences
>>>> and why?
>>> Yes, I'll give it some more documentation. The basic idea is that the
>>> above function also could be
>>> used to validate user supplied data, whereas there might be cases where
>>> we want to use the gem_object_migrate() function and override the
>above.
>>>
>>>
>>>>> +	return false;
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * i915_gem_object_migrate - Migrate an object to the desired region
>id
>>>>> + * @obj: The object to migrate.
>>>>> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend
>may
>>>>> + * not be successful in evicting other objects to make room for this
>object.
>>>> Is the ww for future consideration?  (I don't see any use of it in the
>patch).
>>> Yes, but it will remain optional.
>>>
>>>
>>>>> + * @id: The region id to migrate to.
>>>>> + *
>>>>> + * Attempt to migrate the object to the desired memory region. The
>>>>> + * object backend must support migration and the object may not be
>>>>> + * pinned, (explicitly pinned pages or pinned vmas). The object must
>>>>> + * be locked.
>>>>> + * On successful completion, the object will have pages pointing to
>>>>> + * memory in the new region, but an async migration task may not
>have
>>>>> + * completed yet, and to accomplish that,
>>>>> i915_gem_object_wait_migration()
>>>>> + * must be called.
>>>>> + *
>>>>> + * Return: 0 on success. Negative error code on failure. In particular
>may
>>>>> + * return -ENXIO on lack of region space, -EDEADLK for deadlock
>>> avoidance
>>>>> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
>>>>> + * -EBUSY if the object is pinned.
>>>>> + */
>>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct i915_gem_ww_ctx *ww,
>>>>> +			    enum intel_region_id id)
>>>>> +{
>>>>> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>>>> +	struct intel_memory_region *mr;
>>>>> +
>>>>> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
>>>>> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
>>>>> +	assert_object_held(obj);
>>>>> +
>>>>> +	mr = i915->mm.regions[id];
>>>>> +	GEM_BUG_ON(!mr);
>>>>> +
>>>>> +	if (obj->mm.region == mr)
>>>>> +		return 0;
>>>>> +
>>>>> +	if (!i915_gem_object_evictable(obj))
>>>>> +		return -EBUSY;
>>>>> +
>>>>> +	if (!obj->ops->migrate)
>>>>> +		return -EOPNOTSUPP;
>>>> Why aren't you using _can_migrate here?
>>> It's just in case we want to override. I'll add some more comments about
>>> this.
>>>
>>>>> +	return obj->ops->migrate(obj, mr);
>>>>> +}
>>>>> +
>>>>> void i915_gem_init__objects(struct drm_i915_private *i915)
>>>>> {
>>>>> 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> index ea3224a480c4..8cbd7a5334e2 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>>> @@ -17,6 +17,8 @@
>>>>> #include "i915_gem_ww.h"
>>>>> #include "i915_vma_types.h"
>>>>>
>>>>> +enum intel_region_id;
>>>>> +
>>>>> /*
>>>>>    * XXX: There is a prevalence of the assumption that we fit the
>>>>>    * object's page count inside a 32bit _signed_ variable. Let's document
>>>>> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct
>>>>> drm_i915_gem_object *obj);
>>>>>
>>>>> bool i915_gem_object_validates_to_lmem(struct
>drm_i915_gem_object
>>>>> *obj);
>>>>>
>>>>> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct i915_gem_ww_ctx *ww,
>>>>> +			    enum intel_region_id id);
>>>>> +
>>>>> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object
>*obj,
>>>>> +				 enum intel_region_id id);
>>>>> +
>>>>> +int i915_gem_object_wait_migration(struct drm_i915_gem_object
>*obj,
>>>>> +				   unsigned int flags);
>>>>> +
>>>>> #ifdef CONFIG_MMU_NOTIFIER
>>>>> static inline bool
>>>>> i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
>>>>> 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 441f913c87e6..ef3de2ae9723 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>>>>> @@ -18,6 +18,7 @@
>>>>>
>>>>> struct drm_i915_gem_object;
>>>>> struct intel_fronbuffer;
>>>>> +struct intel_memory_region;
>>>>>
>>>>> /*
>>>>>    * struct i915_lut_handle tracks the fast lookups from handle to vma
>used
>>>>> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>>>>> 	 * delayed_free - Override the default delayed free implementation
>>>>> 	 */
>>>>> 	void (*delayed_free)(struct drm_i915_gem_object *obj);
>>>>> +
>>>>> +	/**
>>>>> +	 * migrate - Migrate object to a different region either for
>>>>> +	 * pinning or for as long as the object lock is held.
>>>>> +	 */
>>>>> +	int (*migrate)(struct drm_i915_gem_object *obj,
>>>>> +		       struct intel_memory_region *mr);
>>>>> +
>>>>> 	void (*release)(struct drm_i915_gem_object *obj);
>>>>>
>>>>> 	const struct vm_operations_struct *mmap_ops;
>>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> index c39d982c4fa6..8f89185b6507 100644
>>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>>>> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>>>>> 	return &i915_ttm_bo_driver;
>>>>> }
>>>>>
>>>>> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>>> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
>>>>> +				struct ttm_placement *placement)
>>>>> {
>>>>> 	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>>>>> 	struct ttm_operation_ctx ctx = {
>>>>> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		.no_wait_gpu = false,
>>>>> 	};
>>>>> 	struct sg_table *st;
>>>>> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>>> -	struct ttm_placement placement;
>>>>> 	int real_num_busy;
>>>>> 	int ret;
>>>>>
>>>>> -	GEM_BUG_ON(obj->mm.n_placements >
>>>>> I915_TTM_MAX_PLACEMENTS);
>>>>> -
>>>>> -	/* Move to the requested placement. */
>>>>> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>>> -
>>>>> 	/* First try only the requested placement. No eviction. */
>>>>> -	real_num_busy =
>>>>> fetch_and_zero(&placement.num_busy_placement);
>>>>> -	ret = ttm_bo_validate(bo, &placement, &ctx);
>>>>> +	real_num_busy = fetch_and_zero(&placement-
>>>>>> num_busy_placement);
>>>>> +	ret = ttm_bo_validate(bo, placement, &ctx);
>>>>> 	if (ret) {
>>>>> 		ret = i915_ttm_err_to_gem(ret);
>>>>> 		/*
>>>>> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		 * If the initial attempt fails, allow all accepted placements,
>>>>> 		 * evicting if necessary.
>>>>> 		 */
>>>>> -		placement.num_busy_placement = real_num_busy;
>>>>> -		ret = ttm_bo_validate(bo, &placement, &ctx);
>>>>> +		placement->num_busy_placement = real_num_busy;
>>>>> +		ret = ttm_bo_validate(bo, placement, &ctx);
>>>>> 		if (ret)
>>>>> 			return i915_ttm_err_to_gem(ret);
>>>>> 	}
>>>>> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct
>>>>> drm_i915_gem_object *obj)
>>>>> 		i915_ttm_adjust_gem_after_move(obj);
>>>>> 	}
>>>>>
>>>>> -	/* Object either has a page vector or is an iomem object */
>>>>> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
>>>>> -	if (IS_ERR(st))
>>>>> -		return PTR_ERR(st);
>>>>> +	if (!obj->mm.pages) {
>>>>> +		/* Object either has a page vector or is an iomem object */
>>>>> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj-
>>>>>> ttm.cached_io_st;
>>>>> +		if (IS_ERR(st))
>>>>> +			return PTR_ERR(st);
>>>>>
>>>>> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
>>>>> +		__i915_gem_object_set_pages(obj, st,
>>>>> i915_sg_dma_sizes(st->sgl));
>>>>> +	}
>>>>>
>>>>> 	return ret;
>>>>> }
>>>>>
>>>>> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>>>>> +{
>>>>> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>>>>> +	struct ttm_placement placement;
>>>>> +
>>>>> +	GEM_BUG_ON(obj->mm.n_placements >
>>>>> I915_TTM_MAX_PLACEMENTS);
>>>>> +
>>>>> +	/* Move to the requested placement. */
>>>>> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
>>>>> +
>>>>> +	return __i915_ttm_get_pages(obj, &placement);
>>>>> +}
>>>>> +
>>>>> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
>>>>> +			    struct intel_memory_region *mr)
>>>>> +{
>>>>> +	struct ttm_place requested;
>>>>> +	struct ttm_placement placement;
>>>>> +	int ret;
>>>>> +
>>>>> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
>>>>> +	placement.num_placement = 1;
>>>>> +	placement.num_busy_placement = 1;
>>>>> +	placement.placement = &requested;
>>>>> +	placement.busy_placement = &requested;
>>>>> +
>>>>> +	ret = __i915_ttm_get_pages(obj, &placement);
>>>>> +	if (ret)
>>>>> +		return ret;
>>>>> +
>>>>> +	if (obj->mm.region != mr) {
>>>>> +		i915_gem_object_release_memory_region(obj);
>>>>> +		i915_gem_object_init_memory_region(obj, mr);
>>>>> +	}
>>>> Perhaps a minor nit:
>>>>
>>>> Doing this after we have done the _get_pages() just doesn't seem right.
>>>>
>>>> I.e. we do work on the object, and then we init some portion of it.
>>>>
>>>> Do we need to do this incase the migration/placement fails?  If so,
>>>> maybe a comment to that effect?
>>> This is simply switching memory region under the lock, and to also move
>>> to another memory region list. Is it the naming _release_ and _init_
>>> that is confusing?
>> Hmm, re-reading my question, I am wondering if I was unclear.
>>
>> My "real" question was, can the release/init occur before the _get_pages()?
>>
>> But looking at this some more, I can see answer is probably no.
>>
>> I was going to suggest calling _init_ _set_, but when I looked at it, it was
>> doing init things as well as setting things
>>
>> Maybe just a comment like:
>>
>> /* Complete the migration by updating the memory region info. */
>> if (object->mm...)
>
>Sure, I'll add that. Note that another thread would have to take the
>object lock anyway to inspect both the region and the pages, so it
>shouldn't be confused by the order here.

Understood.

I think I was just disoriented by the pattern. :)

With the added documentation, I think this looks good.

Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>

Mike

>/Thomas
>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for drm/i915/gem: Introduce a migrate interface (rev3)
  2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
                   ` (8 preceding siblings ...)
  (?)
@ 2021-06-28 20:57 ` Patchwork
  -1 siblings, 0 replies; 54+ messages in thread
From: Patchwork @ 2021-06-28 20:57 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 30273 bytes --]

== Series Details ==

Series: drm/i915/gem: Introduce a migrate interface (rev3)
URL   : https://patchwork.freedesktop.org/series/91890/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_10284_full -> Patchwork_20479_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_20479_full:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@gem_eio@hibernate:
    - {shard-rkl-6}:      [PASS][1] -> [FAIL][2] +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-rkl-6/igt@gem_eio@hibernate.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-6/igt@gem_eio@hibernate.html

  * {igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs}:
    - {shard-rkl-2}:      NOTRUN -> [FAIL][3] +38 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-2/igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs.html

  * {igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_mc_ccs}:
    - {shard-rkl-6}:      NOTRUN -> [SKIP][4] +2 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-6/igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html

  * {igt@kms_ccs@pipe-c-ccs-on-another-bo-y_tiled_gen12_mc_ccs}:
    - {shard-rkl-5}:      NOTRUN -> [FAIL][5] +40 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-5/igt@kms_ccs@pipe-c-ccs-on-another-bo-y_tiled_gen12_mc_ccs.html

  * {igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs}:
    - {shard-rkl-1}:      NOTRUN -> [FAIL][6] +48 similar issues
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-1/igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html

  * igt@kms_cursor_crc@pipe-c-cursor-32x10-sliding:
    - {shard-rkl-5}:      NOTRUN -> [SKIP][7] +75 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-5/igt@kms_cursor_crc@pipe-c-cursor-32x10-sliding.html

  * igt@kms_flip@modeset-vs-vblank-race-interruptible:
    - {shard-rkl-2}:      NOTRUN -> [SKIP][8] +85 similar issues
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-2/igt@kms_flip@modeset-vs-vblank-race-interruptible.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs:
    - {shard-rkl-5}:      NOTRUN -> [INCOMPLETE][9]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-5/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile:
    - {shard-rkl-2}:      NOTRUN -> [INCOMPLETE][10] +2 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-2/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt:
    - {shard-rkl-1}:      NOTRUN -> [SKIP][11] +222 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-1/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt.html

  * igt@runner@aborted:
    - {shard-rkl-1}:      [FAIL][12] ([i915#3002]) -> [FAIL][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-rkl-1/igt@runner@aborted.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-rkl-1/igt@runner@aborted.html

  
New tests
---------

  New tests have been introduced between CI_DRM_10284_full and Patchwork_20479_full:

### New IGT tests (1) ###

  * igt@i915_selftest@live@gem_migrate:
    - Statuses : 8 pass(s)
    - Exec time: [0.49, 4.97] s

  

Known issues
------------

  Here are the changes found in Patchwork_20479_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@smoketest:
    - shard-snb:          NOTRUN -> [SKIP][14] ([fdo#109271] / [i915#1099]) +5 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-snb7/igt@gem_ctx_persistence@smoketest.html

  * igt@gem_eio@unwedge-stress:
    - shard-snb:          NOTRUN -> [FAIL][15] ([i915#3354])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-snb7/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-kbl:          [PASS][16] -> [FAIL][17] ([i915#2842]) +1 similar issue
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl1/igt@gem_exec_fair@basic-none@vcs0.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl4/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-none@vcs1:
    - shard-iclb:         NOTRUN -> [FAIL][18] ([i915#2842]) +4 similar issues
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@gem_exec_fair@basic-none@vcs1.html

  * igt@gem_exec_fair@basic-pace-solo@rcs0:
    - shard-tglb:         [PASS][19] -> [FAIL][20] ([i915#2842]) +1 similar issue
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-tglb7/igt@gem_exec_fair@basic-pace-solo@rcs0.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-tglb6/igt@gem_exec_fair@basic-pace-solo@rcs0.html

  * igt@gem_exec_reloc@basic-wide-active@bcs0:
    - shard-skl:          NOTRUN -> [FAIL][21] ([i915#3633]) +3 similar issues
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl8/igt@gem_exec_reloc@basic-wide-active@bcs0.html

  * igt@gem_pread@exhaustion:
    - shard-apl:          NOTRUN -> [WARN][22] ([i915#2658])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl6/igt@gem_pread@exhaustion.html

  * igt@gem_render_copy@y-tiled-to-vebox-linear:
    - shard-iclb:         NOTRUN -> [SKIP][23] ([i915#768])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@gem_render_copy@y-tiled-to-vebox-linear.html

  * igt@gen9_exec_parse@bb-large:
    - shard-apl:          NOTRUN -> [FAIL][24] ([i915#3296])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl3/igt@gen9_exec_parse@bb-large.html

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-skl:          NOTRUN -> [SKIP][25] ([fdo#109271] / [i915#658])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@i915_pm_dc@dc3co-vpb-simulation.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-skl:          NOTRUN -> [FAIL][26] ([i915#454])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl8/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_pm_dc@dc9-dpms:
    - shard-iclb:         NOTRUN -> [INCOMPLETE][27] ([i915#3698])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@i915_pm_dc@dc9-dpms.html

  * igt@i915_pm_lpsp@kms-lpsp@kms-lpsp-dp:
    - shard-apl:          NOTRUN -> [SKIP][28] ([fdo#109271] / [i915#1937])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl8/igt@i915_pm_lpsp@kms-lpsp@kms-lpsp-dp.html

  * igt@i915_pm_rpm@modeset-lpsp-stress:
    - shard-apl:          NOTRUN -> [SKIP][29] ([fdo#109271]) +297 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl2/igt@i915_pm_rpm@modeset-lpsp-stress.html

  * igt@i915_suspend@forcewake:
    - shard-apl:          [PASS][30] -> [DMESG-WARN][31] ([i915#180])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-apl2/igt@i915_suspend@forcewake.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl8/igt@i915_suspend@forcewake.html

  * igt@kms_big_fb@linear-8bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][32] ([fdo#110725] / [fdo#111614])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_big_fb@linear-8bpp-rotate-270.html

  * igt@kms_big_fb@y-tiled-32bpp-rotate-0:
    - shard-glk:          [PASS][33] -> [DMESG-WARN][34] ([i915#118] / [i915#95]) +2 similar issues
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-glk5/igt@kms_big_fb@y-tiled-32bpp-rotate-0.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-glk5/igt@kms_big_fb@y-tiled-32bpp-rotate-0.html

  * igt@kms_chamelium@dp-crc-multiple:
    - shard-skl:          NOTRUN -> [SKIP][35] ([fdo#109271] / [fdo#111827]) +7 similar issues
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@kms_chamelium@dp-crc-multiple.html

  * igt@kms_chamelium@hdmi-hpd:
    - shard-iclb:         NOTRUN -> [SKIP][36] ([fdo#109284] / [fdo#111827])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_chamelium@hdmi-hpd.html

  * igt@kms_chamelium@hdmi-hpd-storm-disable:
    - shard-kbl:          NOTRUN -> [SKIP][37] ([fdo#109271] / [fdo#111827]) +16 similar issues
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl3/igt@kms_chamelium@hdmi-hpd-storm-disable.html

  * igt@kms_chamelium@hdmi-mode-timings:
    - shard-snb:          NOTRUN -> [SKIP][38] ([fdo#109271] / [fdo#111827]) +23 similar issues
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-snb6/igt@kms_chamelium@hdmi-mode-timings.html

  * igt@kms_color@pipe-c-ctm-0-5:
    - shard-skl:          NOTRUN -> [DMESG-WARN][39] ([i915#1982])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@kms_color@pipe-c-ctm-0-5.html

  * igt@kms_color_chamelium@pipe-a-ctm-limited-range:
    - shard-apl:          NOTRUN -> [SKIP][40] ([fdo#109271] / [fdo#111827]) +33 similar issues
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl6/igt@kms_color_chamelium@pipe-a-ctm-limited-range.html

  * igt@kms_content_protection@atomic-dpms:
    - shard-apl:          NOTRUN -> [TIMEOUT][41] ([i915#1319]) +2 similar issues
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl2/igt@kms_content_protection@atomic-dpms.html
    - shard-kbl:          NOTRUN -> [TIMEOUT][42] ([i915#1319])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl6/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_content_protection@uevent:
    - shard-kbl:          NOTRUN -> [FAIL][43] ([i915#2105])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl3/igt@kms_content_protection@uevent.html
    - shard-apl:          NOTRUN -> [FAIL][44] ([i915#2105])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl3/igt@kms_content_protection@uevent.html

  * igt@kms_cursor_crc@pipe-a-cursor-32x32-onscreen:
    - shard-iclb:         NOTRUN -> [SKIP][45] ([fdo#109278]) +2 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_cursor_crc@pipe-a-cursor-32x32-onscreen.html

  * igt@kms_draw_crc@draw-method-xrgb8888-render-ytiled:
    - shard-skl:          [PASS][46] -> [DMESG-WARN][47] ([i915#1982]) +1 similar issue
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl1/igt@kms_draw_crc@draw-method-xrgb8888-render-ytiled.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl10/igt@kms_draw_crc@draw-method-xrgb8888-render-ytiled.html

  * igt@kms_flip@2x-flip-vs-dpms:
    - shard-iclb:         NOTRUN -> [SKIP][48] ([fdo#109274])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_flip@2x-flip-vs-dpms.html

  * igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2:
    - shard-glk:          [PASS][49] -> [FAIL][50] ([i915#79])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-glk8/igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-glk2/igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [PASS][51] -> [DMESG-WARN][52] ([i915#180]) +8 similar issues
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl2/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl6/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip@flip-vs-suspend@a-dp1:
    - shard-kbl:          NOTRUN -> [DMESG-WARN][53] ([i915#180]) +1 similar issue
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl1/igt@kms_flip@flip-vs-suspend@a-dp1.html

  * igt@kms_flip@plain-flip-fb-recreate@a-edp1:
    - shard-skl:          [PASS][54] -> [FAIL][55] ([i915#2122]) +1 similar issue
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl3/igt@kms_flip@plain-flip-fb-recreate@a-edp1.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl5/igt@kms_flip@plain-flip-fb-recreate@a-edp1.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs:
    - shard-iclb:         NOTRUN -> [SKIP][56] ([i915#2587])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-render:
    - shard-iclb:         NOTRUN -> [SKIP][57] ([fdo#109280]) +2 similar issues
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-blt:
    - shard-skl:          NOTRUN -> [SKIP][58] ([fdo#109271]) +89 similar issues
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-wc:
    - shard-kbl:          NOTRUN -> [SKIP][59] ([fdo#109271]) +138 similar issues
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl3/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-rgb101010-draw-pwrite:
    - shard-skl:          [PASS][60] -> [FAIL][61] ([i915#49])
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl10/igt@kms_frontbuffer_tracking@psr-rgb101010-draw-pwrite.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl7/igt@kms_frontbuffer_tracking@psr-rgb101010-draw-pwrite.html

  * igt@kms_hdr@bpc-switch:
    - shard-skl:          NOTRUN -> [FAIL][62] ([i915#1188])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@kms_hdr@bpc-switch.html

  * igt@kms_hdr@bpc-switch-suspend:
    - shard-skl:          [PASS][63] -> [FAIL][64] ([i915#1188])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl4/igt@kms_hdr@bpc-switch-suspend.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl6/igt@kms_hdr@bpc-switch-suspend.html

  * igt@kms_pipe_crc_basic@disable-crc-after-crtc-pipe-d:
    - shard-kbl:          NOTRUN -> [SKIP][65] ([fdo#109271] / [i915#533])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl3/igt@kms_pipe_crc_basic@disable-crc-after-crtc-pipe-d.html

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-d:
    - shard-skl:          NOTRUN -> [SKIP][66] ([fdo#109271] / [i915#533]) +1 similar issue
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@kms_pipe_crc_basic@hang-read-crc-pipe-d.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-opaque-fb:
    - shard-apl:          NOTRUN -> [FAIL][67] ([fdo#108145] / [i915#265]) +6 similar issues
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl2/igt@kms_plane_alpha_blend@pipe-a-alpha-opaque-fb.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb:
    - shard-skl:          NOTRUN -> [FAIL][68] ([i915#265])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-max:
    - shard-skl:          NOTRUN -> [FAIL][69] ([fdo#108145] / [i915#265])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-max.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-opaque-fb:
    - shard-kbl:          NOTRUN -> [FAIL][70] ([fdo#108145] / [i915#265]) +1 similar issue
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl3/igt@kms_plane_alpha_blend@pipe-b-alpha-opaque-fb.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb:
    - shard-kbl:          NOTRUN -> [FAIL][71] ([i915#265])
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl4/igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          [PASS][72] -> [FAIL][73] ([fdo#108145] / [i915#265]) +1 similar issue
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl9/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  * igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area-2:
    - shard-apl:          NOTRUN -> [SKIP][74] ([fdo#109271] / [i915#658]) +5 similar issues
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl6/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area-2.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-3:
    - shard-kbl:          NOTRUN -> [SKIP][75] ([fdo#109271] / [i915#658]) +3 similar issues
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl6/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area-3.html

  * igt@kms_psr@psr2_cursor_plane_onoff:
    - shard-iclb:         [PASS][76] -> [SKIP][77] ([fdo#109441]) +2 similar issues
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb2/igt@kms_psr@psr2_cursor_plane_onoff.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb6/igt@kms_psr@psr2_cursor_plane_onoff.html

  * igt@kms_vblank@pipe-a-ts-continuation-suspend:
    - shard-kbl:          [PASS][78] -> [DMESG-WARN][79] ([i915#180] / [i915#295])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl4/igt@kms_vblank@pipe-a-ts-continuation-suspend.html
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl1/igt@kms_vblank@pipe-a-ts-continuation-suspend.html

  * igt@kms_vblank@pipe-d-query-forked-hang:
    - shard-snb:          NOTRUN -> [SKIP][80] ([fdo#109271]) +385 similar issues
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-snb7/igt@kms_vblank@pipe-d-query-forked-hang.html

  * igt@kms_vblank@pipe-d-wait-idle:
    - shard-apl:          NOTRUN -> [SKIP][81] ([fdo#109271] / [i915#533]) +1 similar issue
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl3/igt@kms_vblank@pipe-d-wait-idle.html

  * igt@kms_writeback@writeback-fb-id:
    - shard-kbl:          NOTRUN -> [SKIP][82] ([fdo#109271] / [i915#2437]) +1 similar issue
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl4/igt@kms_writeback@writeback-fb-id.html

  * igt@perf@polling-parameterized:
    - shard-skl:          [PASS][83] -> [FAIL][84] ([i915#1542])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl8/igt@perf@polling-parameterized.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl1/igt@perf@polling-parameterized.html

  * igt@sysfs_clients@fair-1:
    - shard-apl:          NOTRUN -> [SKIP][85] ([fdo#109271] / [i915#2994]) +4 similar issues
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-apl3/igt@sysfs_clients@fair-1.html

  * igt@sysfs_clients@sema-10:
    - shard-skl:          NOTRUN -> [SKIP][86] ([fdo#109271] / [i915#2994]) +1 similar issue
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@sysfs_clients@sema-10.html

  * igt@sysfs_clients@split-50:
    - shard-kbl:          NOTRUN -> [SKIP][87] ([fdo#109271] / [i915#2994]) +1 similar issue
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl6/igt@sysfs_clients@split-50.html

  
#### Possible fixes ####

  * igt@gem_eio@in-flight-contexts-10ms:
    - shard-tglb:         [TIMEOUT][88] ([i915#3063]) -> [PASS][89]
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-tglb2/igt@gem_eio@in-flight-contexts-10ms.html
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-tglb5/igt@gem_eio@in-flight-contexts-10ms.html

  * igt@gem_eio@in-flight-suspend:
    - shard-skl:          [INCOMPLETE][90] ([i915#198]) -> [PASS][91]
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl2/igt@gem_eio@in-flight-suspend.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl4/igt@gem_eio@in-flight-suspend.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-glk:          [FAIL][92] ([i915#2846]) -> [PASS][93]
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-glk8/igt@gem_exec_fair@basic-deadline.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-glk2/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-none@vcs1:
    - shard-kbl:          [FAIL][94] ([i915#2842]) -> [PASS][95]
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl1/igt@gem_exec_fair@basic-none@vcs1.html
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl4/igt@gem_exec_fair@basic-none@vcs1.html

  * igt@gem_exec_fair@basic-pace@bcs0:
    - shard-tglb:         [FAIL][96] ([i915#2842]) -> [PASS][97]
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-tglb5/igt@gem_exec_fair@basic-pace@bcs0.html
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-tglb3/igt@gem_exec_fair@basic-pace@bcs0.html
    - shard-iclb:         [FAIL][98] ([i915#2842]) -> [PASS][99]
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb7/igt@gem_exec_fair@basic-pace@bcs0.html
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb8/igt@gem_exec_fair@basic-pace@bcs0.html

  * igt@gem_exec_whisper@basic-queues-forked:
    - shard-iclb:         [INCOMPLETE][100] ([i915#1895] / [i915#2405]) -> [PASS][101]
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb7/igt@gem_exec_whisper@basic-queues-forked.html
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb4/igt@gem_exec_whisper@basic-queues-forked.html

  * igt@gem_mmap_gtt@big-copy-xy:
    - shard-skl:          [FAIL][102] ([i915#307]) -> [PASS][103]
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl4/igt@gem_mmap_gtt@big-copy-xy.html
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl6/igt@gem_mmap_gtt@big-copy-xy.html

  * igt@gem_mmap_gtt@cpuset-big-copy:
    - shard-iclb:         [FAIL][104] ([i915#307]) -> [PASS][105]
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb5/igt@gem_mmap_gtt@cpuset-big-copy.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb2/igt@gem_mmap_gtt@cpuset-big-copy.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-skl:          [DMESG-WARN][106] ([i915#1436] / [i915#716]) -> [PASS][107]
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl10/igt@gen9_exec_parse@allowed-single.html
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl9/igt@gen9_exec_parse@allowed-single.html

  * igt@kms_big_fb@x-tiled-32bpp-rotate-0:
    - shard-glk:          [DMESG-WARN][108] ([i915#118] / [i915#95]) -> [PASS][109]
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-glk7/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-glk7/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html

  * igt@kms_cursor_crc@pipe-a-cursor-suspend:
    - shard-kbl:          [DMESG-WARN][110] ([i915#180]) -> [PASS][111] +4 similar issues
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl1/igt@kms_cursor_crc@pipe-a-cursor-suspend.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl1/igt@kms_cursor_crc@pipe-a-cursor-suspend.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-skl:          [FAIL][112] ([i915#2346]) -> [PASS][113]
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl10/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl6/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-skl:          [FAIL][114] ([i915#2346] / [i915#533]) -> [PASS][115]
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl7/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl2/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-kbl:          [INCOMPLETE][116] ([i915#155] / [i915#180] / [i915#636]) -> [PASS][117]
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-kbl3/igt@kms_fbcon_fbt@fbc-suspend.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-kbl6/igt@kms_fbcon_fbt@fbc-suspend.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@a-hdmi-a2:
    - shard-glk:          [FAIL][118] ([i915#79]) -> [PASS][119]
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-glk7/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-hdmi-a2.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-glk7/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@b-edp1:
    - shard-skl:          [INCOMPLETE][120] ([i915#146] / [i915#198]) -> [PASS][121]
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl2/igt@kms_flip@flip-vs-suspend-interruptible@b-edp1.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl8/igt@kms_flip@flip-vs-suspend-interruptible@b-edp1.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [FAIL][122] ([fdo#108145] / [i915#265]) -> [PASS][123] +1 similar issue
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl2/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl2/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-iclb:         [SKIP][124] ([fdo#109441]) -> [PASS][125] +3 similar issues
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb7/igt@kms_psr@psr2_sprite_plane_move.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb2/igt@kms_psr@psr2_sprite_plane_move.html

  * igt@perf@blocking:
    - shard-skl:          [FAIL][126] ([i915#1542]) -> [PASS][127]
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-skl6/igt@perf@blocking.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-skl3/igt@perf@blocking.html

  
#### Warnings ####

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-iclb:         [SKIP][128] ([i915#658]) -> [SKIP][129] ([i915#588])
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb7/igt@i915_pm_dc@dc3co-vpb-simulation.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb2/igt@i915_pm_dc@dc3co-vpb-simulation.html

  * igt@i915_pm_rc6_residency@rc6-idle:
    - shard-iclb:         [WARN][130] ([i915#2684]) -> [WARN][131] ([i915#1804] / [i915#2684])
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb1/igt@i915_pm_rc6_residency@rc6-idle.html
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb7/igt@i915_pm_rc6_residency@rc6-idle.html

  * igt@kms_dp_dsc@basic-dsc-enable-edp:
    - shard-iclb:         [SKIP][132] ([fdo#109349]) -> [DMESG-WARN][133] ([i915#1226])
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb5/igt@kms_dp_dsc@basic-dsc-enable-edp.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb2/igt@kms_dp_dsc@basic-dsc-enable-edp.html

  * igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area-1:
    - shard-iclb:         [SKIP][134] ([i915#2920]) -> [SKIP][135] ([i915#658]) +2 similar issues
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb2/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area-1.html
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb6/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area-1.html

  * igt@kms_psr2_sf@plane-move-sf-dmg-area-1:
    - shard-iclb:         [SKIP][136] ([i915#658]) -> [SKIP][137] ([i915#2920])
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10284/shard-iclb7/igt@kms_psr2_sf@plane-move-sf-dmg-area-1.html
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/shard-iclb2/igt@kms_psr2_sf@plane-move-sf-dmg-area-1.html

  * igt@runner@aborted:
    - shard-kbl:          ([FAIL][138], [FAIL][139], [FAIL][140], [FAIL][141], [FAIL][142], [FAIL][143], [FAIL][144], [FAIL][145]) ([i915#1436] / [i915#180] / [i915#1814] / [i915#2505] / [i915#3002] / [i915#3363] / [i915#92]) -> ([FAIL][146], [FAIL][147], [FAIL][148], [FAIL][149], [FAIL][150], [FAIL][151], [FAIL][152], [FAIL][153], [FAIL][154]) ([fdo#109271] / [i915#1436] / [i915#180] / [i915#1814] / [i915#2505] / [i915#3002] / [i915#3363] / [i915#602])
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_1

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_20479/index.html

[-- Attachment #1.2: Type: text/html, Size: 33558 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
  2021-06-28 19:45     ` [Intel-gfx] " Ruhl, Michael J
@ 2021-06-29  8:43       ` Daniel Vetter
  -1 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2021-06-29  8:43 UTC (permalink / raw)
  To: Ruhl, Michael J
  Cc: Thomas Hellström, intel-gfx, Auld, Matthew, dri-devel

On Mon, Jun 28, 2021 at 07:45:31PM +0000, Ruhl, Michael J wrote:
> >-----Original Message-----
> >From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >Sent: Monday, June 28, 2021 10:46 AM
> >To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> >Cc: Auld, Matthew <matthew.auld@intel.com>;
> >maarten.lankhorst@linux.intel.com; Thomas Hellström
> ><thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
> ><michael.j.ruhl@intel.com>
> >Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
> >dma-buf export
> >
> >If our exported dma-bufs are imported by another instance of our driver,
> >that instance will typically have the imported dma-bufs locked during
> >map_attachment(). But the exporter also locks the same reservation
> >object in the map_dma_buf() callback, which leads to recursive locking.
> >
> >Add a live selftest to catch this case, and as a workaround until
> >we fully support dynamic import and export, declare the exporter dynamic
> >by providing NOP pin() and unpin() functions. This means our map_dma_buf()
> >callback will *always* get called locked, and by pinning unconditionally
> >in i915_gem_map_dma_buf() we make sure we don't need to use the
> >move_notify() functionality which is not yet implemented.
> 
> An interesting abuse of the interface, but it seems reasonable (for now) to me.

Hm I'm not sure this is the best interface abuse, since if we combine this
with amdgpu it goes boom. Also I thought the dynamic stuff is optional (or
is that only for the importer).

What I discussed a bit with Maarten on irc is to essentially emulate the
rules of what a dynamic exporter would end up with with a non-dynamic
importer: pin/unpin the buffer at attach/detach time. We could fake this
in our attach/detach callbacks.

At least I don't think it's the locking changes that saves us here, but
the caching of the sgt list in attach/detach. As long as we hand-roll that
we should be fine. So hand-rolling that feels like the best option to make
sure we're not making this worse, as long as we haven't fully validated
the true dynamic importer _and_ exporter case.

Cheers, Daniel

> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
> 
> Mike
> 
> >Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
> >Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
> >Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >---
> > drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
> > .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
> >++++++++++++++++++-
> > 2 files changed, 108 insertions(+), 4 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >index 616c3a2f1baf..1d1eeb167d28 100644
> >--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >@@ -12,6 +12,8 @@
> > #include "i915_gem_object.h"
> > #include "i915_scatterlist.h"
> >
> >+I915_SELFTEST_DECLARE(static bool force_different_devices;)
> >+
> > static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
> > {
> > 	return to_intel_bo(buf->priv);
> >@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
> >dma_buf_attachment *attachme
> > 	struct scatterlist *src, *dst;
> > 	int ret, i;
> >
> >-	ret = i915_gem_object_pin_pages_unlocked(obj);
> >+	assert_object_held(obj);
> >+
> >+	ret = i915_gem_object_pin_pages(obj);
> > 	if (ret)
> > 		goto err;
> >
> >@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
> >*dma_buf, enum dma_data_direct
> > 	return err;
> > }
> >
> >+/*
> >+ * As a workaround until we fully support dynamic import and export,
> >+ * declare the exporter dynamic by providing NOP pin() and unpin()
> >functions.
> >+ * This means our i915_gem_map_dma_buf() callback will *always* get
> >called
> >+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
> >make
> >+ * sure we don't need to use the move_notify() functionality which is
> >+ * not yet implemented. Typically for the same-driver-another-instance case,
> >+ * i915_gem_map_dma_buf() will be called at importer attach time and the
> >+ * mapped sg_list will be cached by the dma-buf core for the
> >+ * duration of the attachment.
> >+ */
> >+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
> >+{
> >+	return 0;
> >+}
> >+
> >+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
> >+{
> >+}
> >+
> > static const struct dma_buf_ops i915_dmabuf_ops =  {
> > 	.map_dma_buf = i915_gem_map_dma_buf,
> > 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
> >@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
> > 	.vunmap = i915_gem_dmabuf_vunmap,
> > 	.begin_cpu_access = i915_gem_begin_cpu_access,
> > 	.end_cpu_access = i915_gem_end_cpu_access,
> >+	.pin = i915_gem_dmabuf_pin,
> >+	.unpin = i915_gem_dmabuf_unpin,
> > };
> >
> > struct dma_buf *i915_gem_prime_export(struct drm_gem_object
> >*gem_obj, int flags)
> >@@ -241,7 +267,8 @@ struct drm_gem_object
> >*i915_gem_prime_import(struct drm_device *dev,
> > 	if (dma_buf->ops == &i915_dmabuf_ops) {
> > 		obj = dma_buf_to_obj(dma_buf);
> > 		/* is it from our device? */
> >-		if (obj->base.dev == dev) {
> >+		if (obj->base.dev == dev &&
> >+		    !I915_SELFTEST_ONLY(force_different_devices)) {
> > 			/*
> > 			 * Importing dmabuf exported from out own gem
> >increases
> > 			 * refcount on gem itself instead of f_count of
> >dmabuf.
> >diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >index dd74bc09ec88..24735d6c12a2 100644
> >--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
> > static int igt_dmabuf_import_self(void *arg)
> > {
> > 	struct drm_i915_private *i915 = arg;
> >-	struct drm_i915_gem_object *obj;
> >+	struct drm_i915_gem_object *obj, *import_obj;
> > 	struct drm_gem_object *import;
> > 	struct dma_buf *dmabuf;
> > 	int err;
> >@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
> > 		err = -EINVAL;
> > 		goto out_import;
> > 	}
> >+	import_obj = to_intel_bo(import);
> >+
> >+	i915_gem_object_lock(import_obj, NULL);
> >+	err = ____i915_gem_object_get_pages(import_obj);
> >+	i915_gem_object_unlock(import_obj);
> >+	if (err) {
> >+		pr_err("Same object dma-buf get_pages failed!\n");
> >+		goto out_import;
> >+	}
> >
> > 	err = 0;
> > out_import:
> >-	i915_gem_object_put(to_intel_bo(import));
> >+	i915_gem_object_put(import_obj);
> >+out_dmabuf:
> >+	dma_buf_put(dmabuf);
> >+out:
> >+	i915_gem_object_put(obj);
> >+	return err;
> >+}
> >+
> >+static int igt_dmabuf_import_same_driver(void *arg)
> >+{
> >+	struct drm_i915_private *i915 = arg;
> >+	struct drm_i915_gem_object *obj, *import_obj;
> >+	struct drm_gem_object *import;
> >+	struct dma_buf *dmabuf;
> >+	int err;
> >+
> >+	force_different_devices = true;
> >+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> >+	if (IS_ERR(obj))
> >+		goto out_ret;
> >+
> >+	dmabuf = i915_gem_prime_export(&obj->base, 0);
> >+	if (IS_ERR(dmabuf)) {
> >+		pr_err("i915_gem_prime_export failed with err=%d\n",
> >+		       (int)PTR_ERR(dmabuf));
> >+		err = PTR_ERR(dmabuf);
> >+		goto out;
> >+	}
> >+
> >+	import = i915_gem_prime_import(&i915->drm, dmabuf);
> >+	if (IS_ERR(import)) {
> >+		pr_err("i915_gem_prime_import failed with err=%d\n",
> >+		       (int)PTR_ERR(import));
> >+		err = PTR_ERR(import);
> >+		goto out_dmabuf;
> >+	}
> >+
> >+	if (import == &obj->base) {
> >+		pr_err("i915_gem_prime_import reused gem object!\n");
> >+		err = -EINVAL;
> >+		goto out_import;
> >+	}
> >+
> >+	import_obj = to_intel_bo(import);
> >+
> >+	i915_gem_object_lock(import_obj, NULL);
> >+	err = ____i915_gem_object_get_pages(import_obj);
> >+	if (err) {
> >+		pr_err("Different objects dma-buf get_pages failed!\n");
> >+		i915_gem_object_unlock(import_obj);
> >+		goto out_import;
> >+	}
> >+
> >+	/*
> >+	 * If the exported object is not in system memory, something
> >+	 * weird is going on. TODO: When p2p is supported, this is no
> >+	 * longer considered weird.
> >+	 */
> >+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
> >+		pr_err("Exported dma-buf is not in system memory\n");
> >+		err = -EINVAL;
> >+	}
> >+	i915_gem_object_unlock(import_obj);
> >+
> >+out_import:
> >+	i915_gem_object_put(import_obj);
> > out_dmabuf:
> > 	dma_buf_put(dmabuf);
> > out:
> > 	i915_gem_object_put(obj);
> >+out_ret:
> >+	force_different_devices = false;
> > 	return err;
> > }
> >
> >@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
> >drm_i915_private *i915)
> > {
> > 	static const struct i915_subtest tests[] = {
> > 		SUBTEST(igt_dmabuf_export),
> >+		SUBTEST(igt_dmabuf_import_same_driver),
> > 	};
> >
> > 	return i915_subtests(tests, i915);
> >--
> >2.31.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
@ 2021-06-29  8:43       ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2021-06-29  8:43 UTC (permalink / raw)
  To: Ruhl, Michael J
  Cc: Thomas Hellström, intel-gfx, Auld, Matthew, dri-devel

On Mon, Jun 28, 2021 at 07:45:31PM +0000, Ruhl, Michael J wrote:
> >-----Original Message-----
> >From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >Sent: Monday, June 28, 2021 10:46 AM
> >To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
> >Cc: Auld, Matthew <matthew.auld@intel.com>;
> >maarten.lankhorst@linux.intel.com; Thomas Hellström
> ><thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
> ><michael.j.ruhl@intel.com>
> >Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
> >dma-buf export
> >
> >If our exported dma-bufs are imported by another instance of our driver,
> >that instance will typically have the imported dma-bufs locked during
> >map_attachment(). But the exporter also locks the same reservation
> >object in the map_dma_buf() callback, which leads to recursive locking.
> >
> >Add a live selftest to catch this case, and as a workaround until
> >we fully support dynamic import and export, declare the exporter dynamic
> >by providing NOP pin() and unpin() functions. This means our map_dma_buf()
> >callback will *always* get called locked, and by pinning unconditionally
> >in i915_gem_map_dma_buf() we make sure we don't need to use the
> >move_notify() functionality which is not yet implemented.
> 
> An interesting abuse of the interface, but it seems reasonable (for now) to me.

Hm I'm not sure this is the best interface abuse, since if we combine this
with amdgpu it goes boom. Also I thought the dynamic stuff is optional (or
is that only for the importer).

What I discussed a bit with Maarten on irc is to essentially emulate the
rules of what a dynamic exporter would end up with with a non-dynamic
importer: pin/unpin the buffer at attach/detach time. We could fake this
in our attach/detach callbacks.

At least I don't think it's the locking changes that saves us here, but
the caching of the sgt list in attach/detach. As long as we hand-roll that
we should be fine. So hand-rolling that feels like the best option to make
sure we're not making this worse, as long as we haven't fully validated
the true dynamic importer _and_ exporter case.

Cheers, Daniel

> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
> 
> Mike
> 
> >Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
> >Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
> >Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >---
> > drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
> > .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
> >++++++++++++++++++-
> > 2 files changed, 108 insertions(+), 4 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >index 616c3a2f1baf..1d1eeb167d28 100644
> >--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> >@@ -12,6 +12,8 @@
> > #include "i915_gem_object.h"
> > #include "i915_scatterlist.h"
> >
> >+I915_SELFTEST_DECLARE(static bool force_different_devices;)
> >+
> > static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
> > {
> > 	return to_intel_bo(buf->priv);
> >@@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
> >dma_buf_attachment *attachme
> > 	struct scatterlist *src, *dst;
> > 	int ret, i;
> >
> >-	ret = i915_gem_object_pin_pages_unlocked(obj);
> >+	assert_object_held(obj);
> >+
> >+	ret = i915_gem_object_pin_pages(obj);
> > 	if (ret)
> > 		goto err;
> >
> >@@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
> >*dma_buf, enum dma_data_direct
> > 	return err;
> > }
> >
> >+/*
> >+ * As a workaround until we fully support dynamic import and export,
> >+ * declare the exporter dynamic by providing NOP pin() and unpin()
> >functions.
> >+ * This means our i915_gem_map_dma_buf() callback will *always* get
> >called
> >+ * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
> >make
> >+ * sure we don't need to use the move_notify() functionality which is
> >+ * not yet implemented. Typically for the same-driver-another-instance case,
> >+ * i915_gem_map_dma_buf() will be called at importer attach time and the
> >+ * mapped sg_list will be cached by the dma-buf core for the
> >+ * duration of the attachment.
> >+ */
> >+static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
> >+{
> >+	return 0;
> >+}
> >+
> >+static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
> >+{
> >+}
> >+
> > static const struct dma_buf_ops i915_dmabuf_ops =  {
> > 	.map_dma_buf = i915_gem_map_dma_buf,
> > 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
> >@@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
> > 	.vunmap = i915_gem_dmabuf_vunmap,
> > 	.begin_cpu_access = i915_gem_begin_cpu_access,
> > 	.end_cpu_access = i915_gem_end_cpu_access,
> >+	.pin = i915_gem_dmabuf_pin,
> >+	.unpin = i915_gem_dmabuf_unpin,
> > };
> >
> > struct dma_buf *i915_gem_prime_export(struct drm_gem_object
> >*gem_obj, int flags)
> >@@ -241,7 +267,8 @@ struct drm_gem_object
> >*i915_gem_prime_import(struct drm_device *dev,
> > 	if (dma_buf->ops == &i915_dmabuf_ops) {
> > 		obj = dma_buf_to_obj(dma_buf);
> > 		/* is it from our device? */
> >-		if (obj->base.dev == dev) {
> >+		if (obj->base.dev == dev &&
> >+		    !I915_SELFTEST_ONLY(force_different_devices)) {
> > 			/*
> > 			 * Importing dmabuf exported from out own gem
> >increases
> > 			 * refcount on gem itself instead of f_count of
> >dmabuf.
> >diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >index dd74bc09ec88..24735d6c12a2 100644
> >--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
> >@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
> > static int igt_dmabuf_import_self(void *arg)
> > {
> > 	struct drm_i915_private *i915 = arg;
> >-	struct drm_i915_gem_object *obj;
> >+	struct drm_i915_gem_object *obj, *import_obj;
> > 	struct drm_gem_object *import;
> > 	struct dma_buf *dmabuf;
> > 	int err;
> >@@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
> > 		err = -EINVAL;
> > 		goto out_import;
> > 	}
> >+	import_obj = to_intel_bo(import);
> >+
> >+	i915_gem_object_lock(import_obj, NULL);
> >+	err = ____i915_gem_object_get_pages(import_obj);
> >+	i915_gem_object_unlock(import_obj);
> >+	if (err) {
> >+		pr_err("Same object dma-buf get_pages failed!\n");
> >+		goto out_import;
> >+	}
> >
> > 	err = 0;
> > out_import:
> >-	i915_gem_object_put(to_intel_bo(import));
> >+	i915_gem_object_put(import_obj);
> >+out_dmabuf:
> >+	dma_buf_put(dmabuf);
> >+out:
> >+	i915_gem_object_put(obj);
> >+	return err;
> >+}
> >+
> >+static int igt_dmabuf_import_same_driver(void *arg)
> >+{
> >+	struct drm_i915_private *i915 = arg;
> >+	struct drm_i915_gem_object *obj, *import_obj;
> >+	struct drm_gem_object *import;
> >+	struct dma_buf *dmabuf;
> >+	int err;
> >+
> >+	force_different_devices = true;
> >+	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
> >+	if (IS_ERR(obj))
> >+		goto out_ret;
> >+
> >+	dmabuf = i915_gem_prime_export(&obj->base, 0);
> >+	if (IS_ERR(dmabuf)) {
> >+		pr_err("i915_gem_prime_export failed with err=%d\n",
> >+		       (int)PTR_ERR(dmabuf));
> >+		err = PTR_ERR(dmabuf);
> >+		goto out;
> >+	}
> >+
> >+	import = i915_gem_prime_import(&i915->drm, dmabuf);
> >+	if (IS_ERR(import)) {
> >+		pr_err("i915_gem_prime_import failed with err=%d\n",
> >+		       (int)PTR_ERR(import));
> >+		err = PTR_ERR(import);
> >+		goto out_dmabuf;
> >+	}
> >+
> >+	if (import == &obj->base) {
> >+		pr_err("i915_gem_prime_import reused gem object!\n");
> >+		err = -EINVAL;
> >+		goto out_import;
> >+	}
> >+
> >+	import_obj = to_intel_bo(import);
> >+
> >+	i915_gem_object_lock(import_obj, NULL);
> >+	err = ____i915_gem_object_get_pages(import_obj);
> >+	if (err) {
> >+		pr_err("Different objects dma-buf get_pages failed!\n");
> >+		i915_gem_object_unlock(import_obj);
> >+		goto out_import;
> >+	}
> >+
> >+	/*
> >+	 * If the exported object is not in system memory, something
> >+	 * weird is going on. TODO: When p2p is supported, this is no
> >+	 * longer considered weird.
> >+	 */
> >+	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
> >+		pr_err("Exported dma-buf is not in system memory\n");
> >+		err = -EINVAL;
> >+	}
> >+	i915_gem_object_unlock(import_obj);
> >+
> >+out_import:
> >+	i915_gem_object_put(import_obj);
> > out_dmabuf:
> > 	dma_buf_put(dmabuf);
> > out:
> > 	i915_gem_object_put(obj);
> >+out_ret:
> >+	force_different_devices = false;
> > 	return err;
> > }
> >
> >@@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
> >drm_i915_private *i915)
> > {
> > 	static const struct i915_subtest tests[] = {
> > 		SUBTEST(igt_dmabuf_export),
> >+		SUBTEST(igt_dmabuf_import_same_driver),
> > 	};
> >
> > 	return i915_subtests(tests, i915);
> >--
> >2.31.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
  2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
@ 2021-06-29  8:47     ` Daniel Vetter
  -1 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2021-06-29  8:47 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx, matthew.auld, dri-devel

On Mon, Jun 28, 2021 at 04:46:22PM +0200, Thomas Hellström wrote:
> Introduce an interface to migrate objects between regions.
> This is primarily intended to migrate objects to LMEM for display and
> to SYSTEM for dma-buf, but might be reused in one form or another for
> performance-based migration.
> 
> v2:
> - Verify that the memory region given as an id really exists.
>   (Reported by Matthew Auld)
> - Call i915_gem_object_{init,release}_memory_region() when switching region
>   to handle also switching region lists. (Reported by Matthew Auld)
> v3:
> - Fix i915_gem_object_can_migrate() to return true if object is already in
>   the correct region, even if the object ops doesn't have a migrate()
>   callback.
> - Update typo in commit message.
> - Fix kerneldoc of i915_gem_object_wait_migration().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Looks reasonable to me as the main interface. I'm a bit on the fence on
hiding everything behind obj->ops, since we're not going to have another
implementation of migrate than the ttm one. But also while everything is
in-flight it's probably good to at least try and maintain some boundaries,
for otherwise the messiness might become unmanageable

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

But don't count this as real review :-)

One suggestion at the very bottom.

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>  drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>  .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>  drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>  5 files changed, 188 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 07e8ff9a8aae..1c18be067b58 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
>  	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>  }
>  
> +/**
> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
> + *
> + * @obj: The object to migrate
> + * @id: The region intended to migrate to
> + *
> + * Check whether the object backend supports migration to the
> + * given region. Note that pinning may affect the ability to migrate.
> + *
> + * Return: true if migration is possible, false otherwise.
> + */
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	unsigned int num_allowed = obj->mm.n_placements;
> +	struct intel_memory_region *mr;
> +	unsigned int i;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +
> +	mr = i915->mm.regions[id];
> +	if (!mr)
> +		return false;
> +
> +	if (obj->mm.region == mr)
> +		return true;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return false;
> +
> +	if (!obj->ops->migrate)
> +		return false;
> +
> +	if (!(obj->flags & I915_BO_ALLOC_USER))
> +		return true;
> +
> +	if (num_allowed == 0)
> +		return false;
> +
> +	for (i = 0; i < num_allowed; ++i) {
> +		if (mr == obj->mm.placements[i])
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * i915_gem_object_migrate - Migrate an object to the desired region id
> + * @obj: The object to migrate.
> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
> + * not be successful in evicting other objects to make room for this object.
> + * @id: The region id to migrate to.
> + *
> + * Attempt to migrate the object to the desired memory region. The
> + * object backend must support migration and the object may not be
> + * pinned, (explicitly pinned pages or pinned vmas). The object must
> + * be locked.
> + * On successful completion, the object will have pages pointing to
> + * memory in the new region, but an async migration task may not have
> + * completed yet, and to accomplish that, i915_gem_object_wait_migration()
> + * must be called.
> + *
> + * Return: 0 on success. Negative error code on failure. In particular may
> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
> + * -EBUSY if the object is pinned.
> + */
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	struct intel_memory_region *mr;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +	assert_object_held(obj);
> +
> +	mr = i915->mm.regions[id];
> +	GEM_BUG_ON(!mr);
> +
> +	if (obj->mm.region == mr)
> +		return 0;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return -EBUSY;
> +
> +	if (!obj->ops->migrate)
> +		return -EOPNOTSUPP;
> +
> +	return obj->ops->migrate(obj, mr);
> +}
> +
>  void i915_gem_init__objects(struct drm_i915_private *i915)
>  {
>  	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index ea3224a480c4..8cbd7a5334e2 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -17,6 +17,8 @@
>  #include "i915_gem_ww.h"
>  #include "i915_vma_types.h"
>  
> +enum intel_region_id;
> +
>  /*
>   * XXX: There is a prevalence of the assumption that we fit the
>   * object's page count inside a 32bit _signed_ variable. Let's document
> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
>  
>  bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
>  
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id);
> +
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id);
> +
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags);
> +
>  #ifdef CONFIG_MMU_NOTIFIER
>  static inline bool
>  i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
> 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 441f913c87e6..ef3de2ae9723 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> @@ -18,6 +18,7 @@
>  
>  struct drm_i915_gem_object;
>  struct intel_fronbuffer;
> +struct intel_memory_region;
>  
>  /*
>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>  	 * delayed_free - Override the default delayed free implementation
>  	 */
>  	void (*delayed_free)(struct drm_i915_gem_object *obj);
> +
> +	/**
> +	 * migrate - Migrate object to a different region either for
> +	 * pinning or for as long as the object lock is held.
> +	 */
> +	int (*migrate)(struct drm_i915_gem_object *obj,
> +		       struct intel_memory_region *mr);
> +
>  	void (*release)(struct drm_i915_gem_object *obj);
>  
>  	const struct vm_operations_struct *mmap_ops;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index c39d982c4fa6..8f89185b6507 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>  	return &i915_ttm_bo_driver;
>  }
>  
> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
> +				struct ttm_placement *placement)
>  {
>  	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>  	struct ttm_operation_ctx ctx = {
> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		.no_wait_gpu = false,
>  	};
>  	struct sg_table *st;
> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> -	struct ttm_placement placement;
>  	int real_num_busy;
>  	int ret;
>  
> -	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> -
> -	/* Move to the requested placement. */
> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> -
>  	/* First try only the requested placement. No eviction. */
> -	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
> -	ret = ttm_bo_validate(bo, &placement, &ctx);
> +	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
> +	ret = ttm_bo_validate(bo, placement, &ctx);
>  	if (ret) {
>  		ret = i915_ttm_err_to_gem(ret);
>  		/*
> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		 * If the initial attempt fails, allow all accepted placements,
>  		 * evicting if necessary.
>  		 */
> -		placement.num_busy_placement = real_num_busy;
> -		ret = ttm_bo_validate(bo, &placement, &ctx);
> +		placement->num_busy_placement = real_num_busy;
> +		ret = ttm_bo_validate(bo, placement, &ctx);
>  		if (ret)
>  			return i915_ttm_err_to_gem(ret);
>  	}
> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		i915_ttm_adjust_gem_after_move(obj);
>  	}
>  
> -	/* Object either has a page vector or is an iomem object */
> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> -	if (IS_ERR(st))
> -		return PTR_ERR(st);
> +	if (!obj->mm.pages) {
> +		/* Object either has a page vector or is an iomem object */
> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> +		if (IS_ERR(st))
> +			return PTR_ERR(st);
>  
> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +	}
>  
>  	return ret;
>  }
>  
> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +{
> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> +	struct ttm_placement placement;
> +
> +	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> +
> +	/* Move to the requested placement. */
> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> +
> +	return __i915_ttm_get_pages(obj, &placement);
> +}
> +
> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
> +			    struct intel_memory_region *mr)
> +{
> +	struct ttm_place requested;
> +	struct ttm_placement placement;
> +	int ret;
> +
> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
> +	placement.num_placement = 1;
> +	placement.num_busy_placement = 1;
> +	placement.placement = &requested;
> +	placement.busy_placement = &requested;
> +
> +	ret = __i915_ttm_get_pages(obj, &placement);
> +	if (ret)
> +		return ret;
> +
> +	if (obj->mm.region != mr) {
> +		i915_gem_object_release_memory_region(obj);
> +		i915_gem_object_init_memory_region(obj, mr);
> +	}
> +
> +	return 0;
> +}
> +
>  static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>  			       struct sg_table *st)
>  {
> @@ -814,6 +848,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,
> +	.migrate = i915_ttm_migrate,
>  	.mmap_offset = i915_ttm_mmap_offset,
>  	.mmap_ops = &vm_ops_ttm,
>  };
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> index 1070d3afdce7..f909aaa09d9c 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>  	i915_gem_object_put(obj);
>  	return ret;
>  }
> +
> +/**
> + * i915_gem_object_wait_migration - Sync an accelerated migration operation
> + * @obj: The migrating object.
> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
> + *
> + * Wait for any pending async migration operation on the object,
> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
> + * (swapin, initial clearing) initiated.
> + *
> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
> + */
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags)
> +{
> +	might_sleep();
> +	/* NOP for now. */

Maybe dma_fence_might_wait() here, since that's a notch more nasty?

Cheers, Daniel

> +	return 0;
> +}
> -- 
> 2.31.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 1/5] drm/i915/gem: Implement object migration
@ 2021-06-29  8:47     ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2021-06-29  8:47 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: intel-gfx, matthew.auld, dri-devel

On Mon, Jun 28, 2021 at 04:46:22PM +0200, Thomas Hellström wrote:
> Introduce an interface to migrate objects between regions.
> This is primarily intended to migrate objects to LMEM for display and
> to SYSTEM for dma-buf, but might be reused in one form or another for
> performance-based migration.
> 
> v2:
> - Verify that the memory region given as an id really exists.
>   (Reported by Matthew Auld)
> - Call i915_gem_object_{init,release}_memory_region() when switching region
>   to handle also switching region lists. (Reported by Matthew Auld)
> v3:
> - Fix i915_gem_object_can_migrate() to return true if object is already in
>   the correct region, even if the object ops doesn't have a migrate()
>   callback.
> - Update typo in commit message.
> - Fix kerneldoc of i915_gem_object_wait_migration().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>

Looks reasonable to me as the main interface. I'm a bit on the fence on
hiding everything behind obj->ops, since we're not going to have another
implementation of migrate than the ttm one. But also while everything is
in-flight it's probably good to at least try and maintain some boundaries,
for otherwise the messiness might become unmanageable

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

But don't count this as real review :-)

One suggestion at the very bottom.

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.c    | 96 +++++++++++++++++++
>  drivers/gpu/drm/i915/gem/i915_gem_object.h    | 12 +++
>  .../gpu/drm/i915/gem/i915_gem_object_types.h  |  9 ++
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 69 +++++++++----
>  drivers/gpu/drm/i915/gem/i915_gem_wait.c      | 19 ++++
>  5 files changed, 188 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 07e8ff9a8aae..1c18be067b58 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -513,6 +513,102 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
>  	return obj->mem_flags & I915_BO_FLAG_IOMEM;
>  }
>  
> +/**
> + * i915_gem_object_can_migrate - Whether an object likely can be migrated
> + *
> + * @obj: The object to migrate
> + * @id: The region intended to migrate to
> + *
> + * Check whether the object backend supports migration to the
> + * given region. Note that pinning may affect the ability to migrate.
> + *
> + * Return: true if migration is possible, false otherwise.
> + */
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	unsigned int num_allowed = obj->mm.n_placements;
> +	struct intel_memory_region *mr;
> +	unsigned int i;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +
> +	mr = i915->mm.regions[id];
> +	if (!mr)
> +		return false;
> +
> +	if (obj->mm.region == mr)
> +		return true;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return false;
> +
> +	if (!obj->ops->migrate)
> +		return false;
> +
> +	if (!(obj->flags & I915_BO_ALLOC_USER))
> +		return true;
> +
> +	if (num_allowed == 0)
> +		return false;
> +
> +	for (i = 0; i < num_allowed; ++i) {
> +		if (mr == obj->mm.placements[i])
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +/**
> + * i915_gem_object_migrate - Migrate an object to the desired region id
> + * @obj: The object to migrate.
> + * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
> + * not be successful in evicting other objects to make room for this object.
> + * @id: The region id to migrate to.
> + *
> + * Attempt to migrate the object to the desired memory region. The
> + * object backend must support migration and the object may not be
> + * pinned, (explicitly pinned pages or pinned vmas). The object must
> + * be locked.
> + * On successful completion, the object will have pages pointing to
> + * memory in the new region, but an async migration task may not have
> + * completed yet, and to accomplish that, i915_gem_object_wait_migration()
> + * must be called.
> + *
> + * Return: 0 on success. Negative error code on failure. In particular may
> + * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
> + * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
> + * -EBUSY if the object is pinned.
> + */
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id)
> +{
> +	struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +	struct intel_memory_region *mr;
> +
> +	GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
> +	GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
> +	assert_object_held(obj);
> +
> +	mr = i915->mm.regions[id];
> +	GEM_BUG_ON(!mr);
> +
> +	if (obj->mm.region == mr)
> +		return 0;
> +
> +	if (!i915_gem_object_evictable(obj))
> +		return -EBUSY;
> +
> +	if (!obj->ops->migrate)
> +		return -EOPNOTSUPP;
> +
> +	return obj->ops->migrate(obj, mr);
> +}
> +
>  void i915_gem_init__objects(struct drm_i915_private *i915)
>  {
>  	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index ea3224a480c4..8cbd7a5334e2 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -17,6 +17,8 @@
>  #include "i915_gem_ww.h"
>  #include "i915_vma_types.h"
>  
> +enum intel_region_id;
> +
>  /*
>   * XXX: There is a prevalence of the assumption that we fit the
>   * object's page count inside a 32bit _signed_ variable. Let's document
> @@ -597,6 +599,16 @@ bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
>  
>  bool i915_gem_object_validates_to_lmem(struct drm_i915_gem_object *obj);
>  
> +int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
> +			    struct i915_gem_ww_ctx *ww,
> +			    enum intel_region_id id);
> +
> +bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
> +				 enum intel_region_id id);
> +
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags);
> +
>  #ifdef CONFIG_MMU_NOTIFIER
>  static inline bool
>  i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
> 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 441f913c87e6..ef3de2ae9723 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
> @@ -18,6 +18,7 @@
>  
>  struct drm_i915_gem_object;
>  struct intel_fronbuffer;
> +struct intel_memory_region;
>  
>  /*
>   * struct i915_lut_handle tracks the fast lookups from handle to vma used
> @@ -77,6 +78,14 @@ struct drm_i915_gem_object_ops {
>  	 * delayed_free - Override the default delayed free implementation
>  	 */
>  	void (*delayed_free)(struct drm_i915_gem_object *obj);
> +
> +	/**
> +	 * migrate - Migrate object to a different region either for
> +	 * pinning or for as long as the object lock is held.
> +	 */
> +	int (*migrate)(struct drm_i915_gem_object *obj,
> +		       struct intel_memory_region *mr);
> +
>  	void (*release)(struct drm_i915_gem_object *obj);
>  
>  	const struct vm_operations_struct *mmap_ops;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index c39d982c4fa6..8f89185b6507 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -617,7 +617,8 @@ struct ttm_device_funcs *i915_ttm_driver(void)
>  	return &i915_ttm_bo_driver;
>  }
>  
> -static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
> +				struct ttm_placement *placement)
>  {
>  	struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
>  	struct ttm_operation_ctx ctx = {
> @@ -625,19 +626,12 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		.no_wait_gpu = false,
>  	};
>  	struct sg_table *st;
> -	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> -	struct ttm_placement placement;
>  	int real_num_busy;
>  	int ret;
>  
> -	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> -
> -	/* Move to the requested placement. */
> -	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> -
>  	/* First try only the requested placement. No eviction. */
> -	real_num_busy = fetch_and_zero(&placement.num_busy_placement);
> -	ret = ttm_bo_validate(bo, &placement, &ctx);
> +	real_num_busy = fetch_and_zero(&placement->num_busy_placement);
> +	ret = ttm_bo_validate(bo, placement, &ctx);
>  	if (ret) {
>  		ret = i915_ttm_err_to_gem(ret);
>  		/*
> @@ -652,8 +646,8 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		 * If the initial attempt fails, allow all accepted placements,
>  		 * evicting if necessary.
>  		 */
> -		placement.num_busy_placement = real_num_busy;
> -		ret = ttm_bo_validate(bo, &placement, &ctx);
> +		placement->num_busy_placement = real_num_busy;
> +		ret = ttm_bo_validate(bo, placement, &ctx);
>  		if (ret)
>  			return i915_ttm_err_to_gem(ret);
>  	}
> @@ -668,16 +662,56 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  		i915_ttm_adjust_gem_after_move(obj);
>  	}
>  
> -	/* Object either has a page vector or is an iomem object */
> -	st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> -	if (IS_ERR(st))
> -		return PTR_ERR(st);
> +	if (!obj->mm.pages) {
> +		/* Object either has a page vector or is an iomem object */
> +		st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
> +		if (IS_ERR(st))
> +			return PTR_ERR(st);
>  
> -	__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +		__i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
> +	}
>  
>  	return ret;
>  }
>  
> +static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
> +{
> +	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
> +	struct ttm_placement placement;
> +
> +	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
> +
> +	/* Move to the requested placement. */
> +	i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
> +
> +	return __i915_ttm_get_pages(obj, &placement);
> +}
> +
> +static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
> +			    struct intel_memory_region *mr)
> +{
> +	struct ttm_place requested;
> +	struct ttm_placement placement;
> +	int ret;
> +
> +	i915_ttm_place_from_region(mr, &requested, obj->flags);
> +	placement.num_placement = 1;
> +	placement.num_busy_placement = 1;
> +	placement.placement = &requested;
> +	placement.busy_placement = &requested;
> +
> +	ret = __i915_ttm_get_pages(obj, &placement);
> +	if (ret)
> +		return ret;
> +
> +	if (obj->mm.region != mr) {
> +		i915_gem_object_release_memory_region(obj);
> +		i915_gem_object_init_memory_region(obj, mr);
> +	}
> +
> +	return 0;
> +}
> +
>  static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
>  			       struct sg_table *st)
>  {
> @@ -814,6 +848,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,
> +	.migrate = i915_ttm_migrate,
>  	.mmap_offset = i915_ttm_mmap_offset,
>  	.mmap_ops = &vm_ops_ttm,
>  };
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> index 1070d3afdce7..f909aaa09d9c 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
> @@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>  	i915_gem_object_put(obj);
>  	return ret;
>  }
> +
> +/**
> + * i915_gem_object_wait_migration - Sync an accelerated migration operation
> + * @obj: The migrating object.
> + * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
> + *
> + * Wait for any pending async migration operation on the object,
> + * whether it's explicitly (i915_gem_object_migrate()) or implicitly
> + * (swapin, initial clearing) initiated.
> + *
> + * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
> + */
> +int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
> +				   unsigned int flags)
> +{
> +	might_sleep();
> +	/* NOP for now. */

Maybe dma_fence_might_wait() here, since that's a notch more nasty?

Cheers, Daniel

> +	return 0;
> +}
> -- 
> 2.31.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
  2021-06-29  8:43       ` [Intel-gfx] " Daniel Vetter
@ 2021-06-29  9:36         ` Thomas Hellström
  -1 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-29  9:36 UTC (permalink / raw)
  To: Daniel Vetter, Ruhl, Michael J; +Cc: intel-gfx, Auld, Matthew, dri-devel


On 6/29/21 10:43 AM, Daniel Vetter wrote:
> On Mon, Jun 28, 2021 at 07:45:31PM +0000, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> Sent: Monday, June 28, 2021 10:46 AM
>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Auld, Matthew <matthew.auld@intel.com>;
>>> maarten.lankhorst@linux.intel.com; Thomas Hellström
>>> <thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
>>> <michael.j.ruhl@intel.com>
>>> Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
>>> dma-buf export
>>>
>>> If our exported dma-bufs are imported by another instance of our driver,
>>> that instance will typically have the imported dma-bufs locked during
>>> map_attachment(). But the exporter also locks the same reservation
>>> object in the map_dma_buf() callback, which leads to recursive locking.
>>>
>>> Add a live selftest to catch this case, and as a workaround until
>>> we fully support dynamic import and export, declare the exporter dynamic
>>> by providing NOP pin() and unpin() functions. This means our map_dma_buf()
>>> callback will *always* get called locked, and by pinning unconditionally
>>> in i915_gem_map_dma_buf() we make sure we don't need to use the
>>> move_notify() functionality which is not yet implemented.
>> An interesting abuse of the interface, but it seems reasonable (for now) to me.
> Hm I'm not sure this is the best interface abuse, since if we combine this
> with amdgpu it goes boom. Also I thought the dynamic stuff is optional (or
> is that only for the importer).

I'm not sure what would go wrong here when combined with amdgpu? I 
figure an amdgpu importer being dynamic, would expect to get notified 
using move_notify() on move, but that never happens since the exported 
bo is pinned. If it matters for interface abuse then I could add real 
implementations of pin() and unpin(). But choosing to not evict a mapped 
dma-buf must remain at the exporter's discretion and is not an interface 
abuse IMO.

Could you point me to a case that would not work with this code?

> What I discussed a bit with Maarten on irc is to essentially emulate the
> rules of what a dynamic exporter would end up with with a non-dynamic
> importer: pin/unpin the buffer at attach/detach time. We could fake this
> in our attach/detach callbacks.

Yes, but that would only reimplement what's already in the dma-buf core? 
Since we're about to add a real and correct implementation of this, that 
sounds like a waste of time IMHO.

>
> At least I don't think it's the locking changes that saves us here, but
> the caching of the sgt list in attach/detach.
Yes that saves us for the case of a non-locking non-dynamic importer, 
but for same-driver-another-instance, it's indeed the locking changes.
>   As long as we hand-roll that
> we should be fine. So hand-rolling that feels like the best option to make
> sure we're not making this worse, as long as we haven't fully validated
> the true dynamic importer _and_ exporter case.

/Thomas


>
> Cheers, Daniel
>
>> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>>
>> Mike
>>
>>> Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
>>> Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> ---
>>> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
>>> .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
>>> ++++++++++++++++++-
>>> 2 files changed, 108 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> index 616c3a2f1baf..1d1eeb167d28 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> @@ -12,6 +12,8 @@
>>> #include "i915_gem_object.h"
>>> #include "i915_scatterlist.h"
>>>
>>> +I915_SELFTEST_DECLARE(static bool force_different_devices;)
>>> +
>>> static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
>>> {
>>> 	return to_intel_bo(buf->priv);
>>> @@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>>> dma_buf_attachment *attachme
>>> 	struct scatterlist *src, *dst;
>>> 	int ret, i;
>>>
>>> -	ret = i915_gem_object_pin_pages_unlocked(obj);
>>> +	assert_object_held(obj);
>>> +
>>> +	ret = i915_gem_object_pin_pages(obj);
>>> 	if (ret)
>>> 		goto err;
>>>
>>> @@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
>>> *dma_buf, enum dma_data_direct
>>> 	return err;
>>> }
>>>
>>> +/*
>>> + * As a workaround until we fully support dynamic import and export,
>>> + * declare the exporter dynamic by providing NOP pin() and unpin()
>>> functions.
>>> + * This means our i915_gem_map_dma_buf() callback will *always* get
>>> called
>>> + * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
>>> make
>>> + * sure we don't need to use the move_notify() functionality which is
>>> + * not yet implemented. Typically for the same-driver-another-instance case,
>>> + * i915_gem_map_dma_buf() will be called at importer attach time and the
>>> + * mapped sg_list will be cached by the dma-buf core for the
>>> + * duration of the attachment.
>>> + */
>>> +static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
>>> +{
>>> +}
>>> +
>>> static const struct dma_buf_ops i915_dmabuf_ops =  {
>>> 	.map_dma_buf = i915_gem_map_dma_buf,
>>> 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
>>> @@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
>>> 	.vunmap = i915_gem_dmabuf_vunmap,
>>> 	.begin_cpu_access = i915_gem_begin_cpu_access,
>>> 	.end_cpu_access = i915_gem_end_cpu_access,
>>> +	.pin = i915_gem_dmabuf_pin,
>>> +	.unpin = i915_gem_dmabuf_unpin,
>>> };
>>>
>>> struct dma_buf *i915_gem_prime_export(struct drm_gem_object
>>> *gem_obj, int flags)
>>> @@ -241,7 +267,8 @@ struct drm_gem_object
>>> *i915_gem_prime_import(struct drm_device *dev,
>>> 	if (dma_buf->ops == &i915_dmabuf_ops) {
>>> 		obj = dma_buf_to_obj(dma_buf);
>>> 		/* is it from our device? */
>>> -		if (obj->base.dev == dev) {
>>> +		if (obj->base.dev == dev &&
>>> +		    !I915_SELFTEST_ONLY(force_different_devices)) {
>>> 			/*
>>> 			 * Importing dmabuf exported from out own gem
>>> increases
>>> 			 * refcount on gem itself instead of f_count of
>>> dmabuf.
>>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> index dd74bc09ec88..24735d6c12a2 100644
>>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> @@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
>>> static int igt_dmabuf_import_self(void *arg)
>>> {
>>> 	struct drm_i915_private *i915 = arg;
>>> -	struct drm_i915_gem_object *obj;
>>> +	struct drm_i915_gem_object *obj, *import_obj;
>>> 	struct drm_gem_object *import;
>>> 	struct dma_buf *dmabuf;
>>> 	int err;
>>> @@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
>>> 		err = -EINVAL;
>>> 		goto out_import;
>>> 	}
>>> +	import_obj = to_intel_bo(import);
>>> +
>>> +	i915_gem_object_lock(import_obj, NULL);
>>> +	err = ____i915_gem_object_get_pages(import_obj);
>>> +	i915_gem_object_unlock(import_obj);
>>> +	if (err) {
>>> +		pr_err("Same object dma-buf get_pages failed!\n");
>>> +		goto out_import;
>>> +	}
>>>
>>> 	err = 0;
>>> out_import:
>>> -	i915_gem_object_put(to_intel_bo(import));
>>> +	i915_gem_object_put(import_obj);
>>> +out_dmabuf:
>>> +	dma_buf_put(dmabuf);
>>> +out:
>>> +	i915_gem_object_put(obj);
>>> +	return err;
>>> +}
>>> +
>>> +static int igt_dmabuf_import_same_driver(void *arg)
>>> +{
>>> +	struct drm_i915_private *i915 = arg;
>>> +	struct drm_i915_gem_object *obj, *import_obj;
>>> +	struct drm_gem_object *import;
>>> +	struct dma_buf *dmabuf;
>>> +	int err;
>>> +
>>> +	force_different_devices = true;
>>> +	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>>> +	if (IS_ERR(obj))
>>> +		goto out_ret;
>>> +
>>> +	dmabuf = i915_gem_prime_export(&obj->base, 0);
>>> +	if (IS_ERR(dmabuf)) {
>>> +		pr_err("i915_gem_prime_export failed with err=%d\n",
>>> +		       (int)PTR_ERR(dmabuf));
>>> +		err = PTR_ERR(dmabuf);
>>> +		goto out;
>>> +	}
>>> +
>>> +	import = i915_gem_prime_import(&i915->drm, dmabuf);
>>> +	if (IS_ERR(import)) {
>>> +		pr_err("i915_gem_prime_import failed with err=%d\n",
>>> +		       (int)PTR_ERR(import));
>>> +		err = PTR_ERR(import);
>>> +		goto out_dmabuf;
>>> +	}
>>> +
>>> +	if (import == &obj->base) {
>>> +		pr_err("i915_gem_prime_import reused gem object!\n");
>>> +		err = -EINVAL;
>>> +		goto out_import;
>>> +	}
>>> +
>>> +	import_obj = to_intel_bo(import);
>>> +
>>> +	i915_gem_object_lock(import_obj, NULL);
>>> +	err = ____i915_gem_object_get_pages(import_obj);
>>> +	if (err) {
>>> +		pr_err("Different objects dma-buf get_pages failed!\n");
>>> +		i915_gem_object_unlock(import_obj);
>>> +		goto out_import;
>>> +	}
>>> +
>>> +	/*
>>> +	 * If the exported object is not in system memory, something
>>> +	 * weird is going on. TODO: When p2p is supported, this is no
>>> +	 * longer considered weird.
>>> +	 */
>>> +	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
>>> +		pr_err("Exported dma-buf is not in system memory\n");
>>> +		err = -EINVAL;
>>> +	}
>>> +	i915_gem_object_unlock(import_obj);
>>> +
>>> +out_import:
>>> +	i915_gem_object_put(import_obj);
>>> out_dmabuf:
>>> 	dma_buf_put(dmabuf);
>>> out:
>>> 	i915_gem_object_put(obj);
>>> +out_ret:
>>> +	force_different_devices = false;
>>> 	return err;
>>> }
>>>
>>> @@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
>>> drm_i915_private *i915)
>>> {
>>> 	static const struct i915_subtest tests[] = {
>>> 		SUBTEST(igt_dmabuf_export),
>>> +		SUBTEST(igt_dmabuf_import_same_driver),
>>> 	};
>>>
>>> 	return i915_subtests(tests, i915);
>>> --
>>> 2.31.1

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [Intel-gfx] [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export
@ 2021-06-29  9:36         ` Thomas Hellström
  0 siblings, 0 replies; 54+ messages in thread
From: Thomas Hellström @ 2021-06-29  9:36 UTC (permalink / raw)
  To: Daniel Vetter, Ruhl, Michael J; +Cc: intel-gfx, Auld, Matthew, dri-devel


On 6/29/21 10:43 AM, Daniel Vetter wrote:
> On Mon, Jun 28, 2021 at 07:45:31PM +0000, Ruhl, Michael J wrote:
>>> -----Original Message-----
>>> From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> Sent: Monday, June 28, 2021 10:46 AM
>>> To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org
>>> Cc: Auld, Matthew <matthew.auld@intel.com>;
>>> maarten.lankhorst@linux.intel.com; Thomas Hellström
>>> <thomas.hellstrom@linux.intel.com>; Ruhl; Ruhl, Michael J
>>> <michael.j.ruhl@intel.com>
>>> Subject: [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance
>>> dma-buf export
>>>
>>> If our exported dma-bufs are imported by another instance of our driver,
>>> that instance will typically have the imported dma-bufs locked during
>>> map_attachment(). But the exporter also locks the same reservation
>>> object in the map_dma_buf() callback, which leads to recursive locking.
>>>
>>> Add a live selftest to catch this case, and as a workaround until
>>> we fully support dynamic import and export, declare the exporter dynamic
>>> by providing NOP pin() and unpin() functions. This means our map_dma_buf()
>>> callback will *always* get called locked, and by pinning unconditionally
>>> in i915_gem_map_dma_buf() we make sure we don't need to use the
>>> move_notify() functionality which is not yet implemented.
>> An interesting abuse of the interface, but it seems reasonable (for now) to me.
> Hm I'm not sure this is the best interface abuse, since if we combine this
> with amdgpu it goes boom. Also I thought the dynamic stuff is optional (or
> is that only for the importer).

I'm not sure what would go wrong here when combined with amdgpu? I 
figure an amdgpu importer being dynamic, would expect to get notified 
using move_notify() on move, but that never happens since the exported 
bo is pinned. If it matters for interface abuse then I could add real 
implementations of pin() and unpin(). But choosing to not evict a mapped 
dma-buf must remain at the exporter's discretion and is not an interface 
abuse IMO.

Could you point me to a case that would not work with this code?

> What I discussed a bit with Maarten on irc is to essentially emulate the
> rules of what a dynamic exporter would end up with with a non-dynamic
> importer: pin/unpin the buffer at attach/detach time. We could fake this
> in our attach/detach callbacks.

Yes, but that would only reimplement what's already in the dma-buf core? 
Since we're about to add a real and correct implementation of this, that 
sounds like a waste of time IMHO.

>
> At least I don't think it's the locking changes that saves us here, but
> the caching of the sgt list in attach/detach.
Yes that saves us for the case of a non-locking non-dynamic importer, 
but for same-driver-another-instance, it's indeed the locking changes.
>   As long as we hand-roll that
> we should be fine. So hand-rolling that feels like the best option to make
> sure we're not making this worse, as long as we haven't fully validated
> the true dynamic importer _and_ exporter case.

/Thomas


>
> Cheers, Daniel
>
>> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
>>
>> Mike
>>
>>> Reported-by: Ruhl, Michael J <michael.j.ruhl@intel.com>
>>> Cc: Ruhl, Michael J <michael.j.ruhl@intel.com>
>>> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>> ---
>>> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    | 31 ++++++-
>>> .../drm/i915/gem/selftests/i915_gem_dmabuf.c  | 81
>>> ++++++++++++++++++-
>>> 2 files changed, 108 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> index 616c3a2f1baf..1d1eeb167d28 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
>>> @@ -12,6 +12,8 @@
>>> #include "i915_gem_object.h"
>>> #include "i915_scatterlist.h"
>>>
>>> +I915_SELFTEST_DECLARE(static bool force_different_devices;)
>>> +
>>> static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
>>> {
>>> 	return to_intel_bo(buf->priv);
>>> @@ -25,7 +27,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct
>>> dma_buf_attachment *attachme
>>> 	struct scatterlist *src, *dst;
>>> 	int ret, i;
>>>
>>> -	ret = i915_gem_object_pin_pages_unlocked(obj);
>>> +	assert_object_held(obj);
>>> +
>>> +	ret = i915_gem_object_pin_pages(obj);
>>> 	if (ret)
>>> 		goto err;
>>>
>>> @@ -168,6 +172,26 @@ static int i915_gem_end_cpu_access(struct dma_buf
>>> *dma_buf, enum dma_data_direct
>>> 	return err;
>>> }
>>>
>>> +/*
>>> + * As a workaround until we fully support dynamic import and export,
>>> + * declare the exporter dynamic by providing NOP pin() and unpin()
>>> functions.
>>> + * This means our i915_gem_map_dma_buf() callback will *always* get
>>> called
>>> + * locked, and by pinning unconditionally in i915_gem_map_dma_buf() we
>>> make
>>> + * sure we don't need to use the move_notify() functionality which is
>>> + * not yet implemented. Typically for the same-driver-another-instance case,
>>> + * i915_gem_map_dma_buf() will be called at importer attach time and the
>>> + * mapped sg_list will be cached by the dma-buf core for the
>>> + * duration of the attachment.
>>> + */
>>> +static int i915_gem_dmabuf_pin(struct dma_buf_attachment *attach)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static void i915_gem_dmabuf_unpin(struct dma_buf_attachment *attach)
>>> +{
>>> +}
>>> +
>>> static const struct dma_buf_ops i915_dmabuf_ops =  {
>>> 	.map_dma_buf = i915_gem_map_dma_buf,
>>> 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
>>> @@ -177,6 +201,8 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
>>> 	.vunmap = i915_gem_dmabuf_vunmap,
>>> 	.begin_cpu_access = i915_gem_begin_cpu_access,
>>> 	.end_cpu_access = i915_gem_end_cpu_access,
>>> +	.pin = i915_gem_dmabuf_pin,
>>> +	.unpin = i915_gem_dmabuf_unpin,
>>> };
>>>
>>> struct dma_buf *i915_gem_prime_export(struct drm_gem_object
>>> *gem_obj, int flags)
>>> @@ -241,7 +267,8 @@ struct drm_gem_object
>>> *i915_gem_prime_import(struct drm_device *dev,
>>> 	if (dma_buf->ops == &i915_dmabuf_ops) {
>>> 		obj = dma_buf_to_obj(dma_buf);
>>> 		/* is it from our device? */
>>> -		if (obj->base.dev == dev) {
>>> +		if (obj->base.dev == dev &&
>>> +		    !I915_SELFTEST_ONLY(force_different_devices)) {
>>> 			/*
>>> 			 * Importing dmabuf exported from out own gem
>>> increases
>>> 			 * refcount on gem itself instead of f_count of
>>> dmabuf.
>>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> index dd74bc09ec88..24735d6c12a2 100644
>>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
>>> @@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
>>> static int igt_dmabuf_import_self(void *arg)
>>> {
>>> 	struct drm_i915_private *i915 = arg;
>>> -	struct drm_i915_gem_object *obj;
>>> +	struct drm_i915_gem_object *obj, *import_obj;
>>> 	struct drm_gem_object *import;
>>> 	struct dma_buf *dmabuf;
>>> 	int err;
>>> @@ -65,14 +65,90 @@ static int igt_dmabuf_import_self(void *arg)
>>> 		err = -EINVAL;
>>> 		goto out_import;
>>> 	}
>>> +	import_obj = to_intel_bo(import);
>>> +
>>> +	i915_gem_object_lock(import_obj, NULL);
>>> +	err = ____i915_gem_object_get_pages(import_obj);
>>> +	i915_gem_object_unlock(import_obj);
>>> +	if (err) {
>>> +		pr_err("Same object dma-buf get_pages failed!\n");
>>> +		goto out_import;
>>> +	}
>>>
>>> 	err = 0;
>>> out_import:
>>> -	i915_gem_object_put(to_intel_bo(import));
>>> +	i915_gem_object_put(import_obj);
>>> +out_dmabuf:
>>> +	dma_buf_put(dmabuf);
>>> +out:
>>> +	i915_gem_object_put(obj);
>>> +	return err;
>>> +}
>>> +
>>> +static int igt_dmabuf_import_same_driver(void *arg)
>>> +{
>>> +	struct drm_i915_private *i915 = arg;
>>> +	struct drm_i915_gem_object *obj, *import_obj;
>>> +	struct drm_gem_object *import;
>>> +	struct dma_buf *dmabuf;
>>> +	int err;
>>> +
>>> +	force_different_devices = true;
>>> +	obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
>>> +	if (IS_ERR(obj))
>>> +		goto out_ret;
>>> +
>>> +	dmabuf = i915_gem_prime_export(&obj->base, 0);
>>> +	if (IS_ERR(dmabuf)) {
>>> +		pr_err("i915_gem_prime_export failed with err=%d\n",
>>> +		       (int)PTR_ERR(dmabuf));
>>> +		err = PTR_ERR(dmabuf);
>>> +		goto out;
>>> +	}
>>> +
>>> +	import = i915_gem_prime_import(&i915->drm, dmabuf);
>>> +	if (IS_ERR(import)) {
>>> +		pr_err("i915_gem_prime_import failed with err=%d\n",
>>> +		       (int)PTR_ERR(import));
>>> +		err = PTR_ERR(import);
>>> +		goto out_dmabuf;
>>> +	}
>>> +
>>> +	if (import == &obj->base) {
>>> +		pr_err("i915_gem_prime_import reused gem object!\n");
>>> +		err = -EINVAL;
>>> +		goto out_import;
>>> +	}
>>> +
>>> +	import_obj = to_intel_bo(import);
>>> +
>>> +	i915_gem_object_lock(import_obj, NULL);
>>> +	err = ____i915_gem_object_get_pages(import_obj);
>>> +	if (err) {
>>> +		pr_err("Different objects dma-buf get_pages failed!\n");
>>> +		i915_gem_object_unlock(import_obj);
>>> +		goto out_import;
>>> +	}
>>> +
>>> +	/*
>>> +	 * If the exported object is not in system memory, something
>>> +	 * weird is going on. TODO: When p2p is supported, this is no
>>> +	 * longer considered weird.
>>> +	 */
>>> +	if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
>>> +		pr_err("Exported dma-buf is not in system memory\n");
>>> +		err = -EINVAL;
>>> +	}
>>> +	i915_gem_object_unlock(import_obj);
>>> +
>>> +out_import:
>>> +	i915_gem_object_put(import_obj);
>>> out_dmabuf:
>>> 	dma_buf_put(dmabuf);
>>> out:
>>> 	i915_gem_object_put(obj);
>>> +out_ret:
>>> +	force_different_devices = false;
>>> 	return err;
>>> }
>>>
>>> @@ -286,6 +362,7 @@ int i915_gem_dmabuf_live_selftests(struct
>>> drm_i915_private *i915)
>>> {
>>> 	static const struct i915_subtest tests[] = {
>>> 		SUBTEST(igt_dmabuf_export),
>>> +		SUBTEST(igt_dmabuf_import_same_driver),
>>> 	};
>>>
>>> 	return i915_subtests(tests, i915);
>>> --
>>> 2.31.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2021-06-29  9:36 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-28 14:46 [PATCH v3 0/5] drm/i915/gem: Introduce a migrate interface Thomas Hellström
2021-06-28 14:46 ` [Intel-gfx] " Thomas Hellström
2021-06-28 14:46 ` [PATCH v3 1/5] drm/i915/gem: Implement object migration Thomas Hellström
2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
2021-06-28 16:28   ` Matthew Auld
2021-06-28 16:28     ` [Intel-gfx] " Matthew Auld
2021-06-28 17:34     ` Thomas Hellström
2021-06-28 17:34       ` [Intel-gfx] " Thomas Hellström
2021-06-28 18:11   ` Ruhl, Michael J
2021-06-28 18:11     ` [Intel-gfx] " Ruhl, Michael J
2021-06-28 19:02     ` Thomas Hellström
2021-06-28 19:02       ` [Intel-gfx] " Thomas Hellström
2021-06-28 19:50       ` Ruhl, Michael J
2021-06-28 19:50         ` [Intel-gfx] " Ruhl, Michael J
2021-06-28 19:54         ` Thomas Hellström
2021-06-28 19:54           ` [Intel-gfx] " Thomas Hellström
2021-06-28 20:13           ` Ruhl, Michael J
2021-06-28 20:13             ` [Intel-gfx] " Ruhl, Michael J
2021-06-29  8:47   ` Daniel Vetter
2021-06-29  8:47     ` Daniel Vetter
2021-06-28 14:46 ` [PATCH v3 2/5] drm/i915/gem: Introduce a selftest for the gem object migrate functionality Thomas Hellström
2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
2021-06-28 15:51   ` Matthew Auld
2021-06-28 15:51     ` [Intel-gfx] " Matthew Auld
2021-06-28 18:53   ` Ruhl, Michael J
2021-06-28 18:53     ` Ruhl, Michael J
2021-06-28 19:14     ` Thomas Hellström
2021-06-28 19:14       ` Thomas Hellström
2021-06-28 19:27       ` Ruhl, Michael J
2021-06-28 19:27         ` Ruhl, Michael J
2021-06-28 19:32         ` Thomas Hellström
2021-06-28 19:32           ` Thomas Hellström
2021-06-28 14:46 ` [PATCH v3 3/5] drm/i915/display: Migrate objects to LMEM if possible for display Thomas Hellström
2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
2021-06-28 15:20   ` Matthew Auld
2021-06-28 15:20     ` [Intel-gfx] " Matthew Auld
2021-06-28 14:46 ` [PATCH v3 4/5] drm/i915/gem: Fix same-driver-another-instance dma-buf export Thomas Hellström
2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
2021-06-28 19:45   ` Ruhl, Michael J
2021-06-28 19:45     ` [Intel-gfx] " Ruhl, Michael J
2021-06-29  8:43     ` Daniel Vetter
2021-06-29  8:43       ` [Intel-gfx] " Daniel Vetter
2021-06-29  9:36       ` Thomas Hellström
2021-06-29  9:36         ` [Intel-gfx] " Thomas Hellström
2021-06-28 14:46 ` [PATCH v3 5/5] drm/i915/gem: Migrate to system at dma-buf map time Thomas Hellström
2021-06-28 14:46   ` [Intel-gfx] " Thomas Hellström
2021-06-28 19:45   ` Ruhl, Michael J
2021-06-28 19:45     ` [Intel-gfx] " Ruhl, Michael J
2021-06-28 19:51     ` Thomas Hellström
2021-06-28 19:51       ` [Intel-gfx] " Thomas Hellström
2021-06-28 16:57 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/gem: Introduce a migrate interface (rev3) Patchwork
2021-06-28 16:58 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2021-06-28 17:27 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2021-06-28 20:57 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.