[PATCH 62/65] drm/i915: Update vma to use async page allocations

Chris Wilson chris at chris-wilson.co.uk
Tue Jun 23 22:56:21 UTC 2020


Since we have asynchronous vma bindings, we are ready to utilise
asynchronous page allocations. All we have to do is ask for the
get_pages not to wait on our behalf, as our workqueue will.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c    | 10 ++--
 drivers/gpu/drm/i915/gem/i915_gem_object.h    |  1 +
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     |  2 +-
 drivers/gpu/drm/i915/i915_vma.c               | 51 ++++++++++---------
 drivers/gpu/drm/i915/i915_vma.h               |  7 +++
 drivers/gpu/drm/i915/i915_vma_types.h         |  2 +
 6 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index f122f6e55db5..c5add0d6d97e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -699,6 +699,8 @@ static int set_bind_fence(struct i915_vma *vma, struct eb_vm_work *work)
 
 	lockdep_assert_held(&vma->vm->mutex);
 	prev = i915_active_set_exclusive(&vma->active, &work->base.dma);
+	if (!prev)
+		prev = i915_active_fence_get(&vma->obj->mm.active.excl);
 	if (unlikely(prev)) {
 		err = i915_sw_fence_await_dma_fence(&work->base.chain, prev, 0,
 						    GFP_NOWAIT | __GFP_NOWARN);
@@ -1213,10 +1215,12 @@ static int __eb_bind_vma(struct eb_vm_work *work, int err)
 			err = vma->ops->bind_vma(vma,
 						 vma->obj->cache_level,
 						 ev->bind_flags);
-		if (err == 0)
-			eb_pin_vma_pages(vma, ev->bind_flags);
-		else
+		if (err) {
+			i915_vma_set_error_once(vma, err);
 			atomic_and(~ev->bind_flags, &vma->flags);
+		} else {
+			eb_pin_vma_pages(vma, ev->bind_flags);
+		}
 
 		if (drm_mm_node_allocated(&ev->hole)) {
 			mutex_lock(&vm->mutex);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 9b1d9d979a1f..fdfecbb3346f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -275,6 +275,7 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 				 struct sg_table *pages,
 				 unsigned int sg_page_sizes);
 
+int ____i915_gem_object_get_pages_async(struct drm_i915_gem_object *obj);
 int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 int __i915_gem_object_get_pages_locked(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 0693ed0dbab1..1dd31527ffe0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -95,7 +95,7 @@ static int __i915_gem_object_wait_for_pages(struct drm_i915_gem_object *obj)
 	return 0;
 }
 
-static int ____i915_gem_object_get_pages_async(struct drm_i915_gem_object *obj)
+int ____i915_gem_object_get_pages_async(struct drm_i915_gem_object *obj)
 {
 	int err;
 
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index b34ad6b100e6..fd705f4f13c5 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -123,6 +123,7 @@ vma_create(struct drm_i915_gem_object *obj,
 	vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
 
 	i915_active_init(&vma->active, __i915_vma_active, __i915_vma_retire);
+	vma->fence_context = dma_fence_context_alloc(1);
 
 	/* Declare ourselves safe for use inside shrinkers */
 	if (IS_ENABLED(CONFIG_LOCKDEP)) {
@@ -295,7 +296,6 @@ i915_vma_instance(struct drm_i915_gem_object *obj,
 struct i915_vma_work {
 	struct dma_fence_work base;
 	struct i915_vma *vma;
-	struct drm_i915_gem_object *pinned;
 	struct i915_sw_dma_fence_cb cb;
 	enum i915_cache_level cache_level;
 	unsigned int flags;
@@ -336,12 +336,9 @@ static void __vma_release(struct dma_fence_work *work)
 	if (work->dma.error && vw->flags) {
 		struct i915_vma *vma = vw->vma;
 
-		atomic_or(I915_VMA_ERROR, &vma->flags);
+		i915_vma_set_error_once(vma, work->dma.error);
 		atomic_and(~vw->flags, &vma->flags);
 	}
-
-	if (vw->pinned)
-		__i915_gem_object_unpin_pages(vw->pinned);
 }
 
 static const struct dma_fence_work_ops bind_ops = {
@@ -453,6 +450,8 @@ int i915_vma_bind(struct i915_vma *vma,
 	 * execution and not content or object's backing store lifetime.
 	 */
 	prev = i915_active_set_exclusive(&vma->active, &work->base.dma);
+	if (!prev && vma->obj)
+		prev = i915_active_fence_get(&vma->obj->mm.active.excl);
 	if (prev) {
 		__i915_sw_fence_await_dma_fence(&work->base.chain,
 						prev,
@@ -464,11 +463,6 @@ int i915_vma_bind(struct i915_vma *vma,
 		i915_sw_fence_set_error_once(&work->base.chain,
 					     PTR_ERR(vma->obj->mm.pages));
 
-	if (vma->obj) {
-		__i915_gem_object_pin_pages(vma->obj);
-		work->pinned = vma->obj;
-	}
-
 	atomic_or(bind_flags, &vma->flags);
 	return 0;
 }
@@ -837,20 +831,27 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	if (try_qad_pin(vma, flags & I915_VMA_BIND_MASK))
 		return 0;
 
-	if (vma->obj) {
-		err = i915_gem_object_pin_pages(vma->obj);
-		if (err)
-			return err;
-	}
-
 	err = __wait_for_unbind(vma, flags);
 	if (err)
-		goto err_pages;
+		return err;
 
 	work = i915_vma_work();
-	if (!work) {
-		err = -ENOMEM;
-		goto err_pages;
+	if (!work)
+		return -ENOMEM;
+
+	if (vma->obj) {
+		if (dma_resv_lock_interruptible(vma->resv, NULL))
+			return -EINTR;
+
+		err = ____i915_gem_object_get_pages_async(vma->obj);
+		if (err == 0) {
+			err = i915_active_ref(&vma->obj->mm.active,
+					      vma->fence_context,
+					      &work->base.dma);
+		}
+		dma_resv_unlock(vma->resv);
+		if (err)
+			return err;
 	}
 
 	if (flags & PIN_GLOBAL)
@@ -887,7 +888,7 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
 	bound = atomic_read(&vma->flags);
 	if (unlikely(bound & I915_VMA_ERROR)) {
-		err = -ENOMEM;
+		err = vma->error;
 		goto err_unlock;
 	}
 
@@ -945,9 +946,6 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	dma_fence_work_commit_imm(&work->base);
 	if (wakeref)
 		intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref);
-err_pages:
-	if (vma->obj)
-		i915_gem_object_unpin_pages(vma->obj);
 	return err;
 }
 
@@ -1153,6 +1151,10 @@ int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq)
 	if (err)
 		return err;
 
+	err = READ_ONCE(vma->error);
+	if (err)
+		return err;
+
 	return i915_active_add_request(&vma->active, rq);
 }
 
@@ -1206,6 +1208,7 @@ void __i915_vma_evict(struct i915_vma *vma)
 	int count;
 
 	GEM_BUG_ON(i915_vma_is_pinned(vma));
+	vma->error = 0;
 
 	if (i915_vma_is_map_and_fenceable(vma)) {
 		/* Force a pagefault for domain tracking on next user access */
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
index 8ec204817986..dea651a250df 100644
--- a/drivers/gpu/drm/i915/i915_vma.h
+++ b/drivers/gpu/drm/i915/i915_vma.h
@@ -385,4 +385,11 @@ static inline int i915_vma_sync(struct i915_vma *vma)
 	return i915_active_wait(&vma->active);
 }
 
+static inline void
+i915_vma_set_error_once(struct i915_vma *vma, int error)
+{
+	if (!test_and_set_bit(I915_VMA_ERROR_BIT, __i915_vma_flags(vma)))
+		WRITE_ONCE(vma->error, error);
+}
+
 #endif
diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h
index 02c1640bb034..1b63e854438f 100644
--- a/drivers/gpu/drm/i915/i915_vma_types.h
+++ b/drivers/gpu/drm/i915/i915_vma_types.h
@@ -250,6 +250,8 @@ struct i915_vma {
 #define I915_VMA_GGTT_WRITE	((int)BIT(I915_VMA_GGTT_WRITE_BIT))
 
 	struct i915_active active;
+	u64 fence_context;
+	int error;
 
 	/**
 	 * Support different GGTT views into the same object.
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list