diff mbox series

[1/4] drm/i915: Check i915_active wait status after flushing

Message ID 20200122184249.551268-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series [1/4] drm/i915: Check i915_active wait status after flushing | expand

Commit Message

Chris Wilson Jan. 22, 2020, 6:42 p.m. UTC
Double check that the i915_active is finally idle after waiting, and
flushing its callback, just in case we need to re-activate it, for
example to keep the vma alive a bit longer due to last minute HW
activity (e.g. saving the context before unbinding).

Closes: https://gitlab.freedesktop.org/drm/intel/issues/530
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_active.c | 38 ++++++++++++++++++------------
 1 file changed, 23 insertions(+), 15 deletions(-)

Comments

Chris Wilson Jan. 23, 2020, 3:07 p.m. UTC | #1
Quoting Chris Wilson (2020-01-22 18:42:46)
> Double check that the i915_active is finally idle after waiting, and
> flushing its callback, just in case we need to re-activate it, for
> example to keep the vma alive a bit longer due to last minute HW
> activity (e.g. saving the context before unbinding).
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/issues/530
Fixes: 2850748ef876 ("drm/i915: Pull i915_vma_pin under the vm->mutex")
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index ace55d5d4ca7..204564944dde 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -448,17 +448,11 @@  static void enable_signaling(struct i915_active_fence *active)
 	dma_fence_put(fence);
 }
 
-int i915_active_wait(struct i915_active *ref)
+static int flush_lazy_signals(struct i915_active *ref)
 {
 	struct active_node *it, *n;
 	int err = 0;
 
-	might_sleep();
-
-	if (!i915_active_acquire_if_busy(ref))
-		return 0;
-
-	/* Flush lazy signals */
 	enable_signaling(&ref->excl);
 	rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) {
 		if (is_barrier(&it->base)) /* unconnected idle barrier */
@@ -466,17 +460,31 @@  int i915_active_wait(struct i915_active *ref)
 
 		enable_signaling(&it->base);
 	}
-	/* Any fence added after the wait begins will not be auto-signaled */
 
-	i915_active_release(ref);
-	if (err)
-		return err;
+	return err;
+}
 
-	if (wait_var_event_interruptible(ref, i915_active_is_idle(ref)))
-		return -EINTR;
+int i915_active_wait(struct i915_active *ref)
+{
+	might_sleep();
 
-	flush_work(&ref->work);
-	return 0;
+	do {
+		int err;
+
+		if (!i915_active_acquire_if_busy(ref))
+			return 0;
+
+		/* Any fence added late will not be auto-signaled */
+		err = flush_lazy_signals(ref);
+		i915_active_release(ref);
+		if (err)
+			return err;
+
+		if (wait_var_event_interruptible(ref, i915_active_is_idle(ref)))
+			return -EINTR;
+
+		flush_work(&ref->work);
+	} while (1);
 }
 
 int i915_request_await_active(struct i915_request *rq, struct i915_active *ref)