[Intel-gfx] [PATCH 2/4] drm/i915: Track the error through the sw-fence

Chris Wilson chris at chris-wilson.co.uk
Wed Mar 8 11:40:08 UTC 2017


In order to handle asynchronous error conditions, we need to store the
error status on the fence itself, and inspect it upon signaling.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Cc: Mika Kuoppala <mika.kuoppala at intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_sw_fence.c | 25 ++++++++++++++++++++-----
 drivers/gpu/drm/i915/i915_sw_fence.h |  1 +
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index a277f8eb7beb..49043687effc 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -179,7 +179,7 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
 		do {
 			list_for_each_entry_safe(pos, next,
 						 &x->task_list, task_list)
-				pos->func(pos, TASK_NORMAL, 0, &extra);
+				pos->func(pos, TASK_NORMAL, fence->error, &extra);
 
 			if (list_empty(&extra))
 				break;
@@ -240,6 +240,7 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence,
 	kref_init(&fence->kref);
 	atomic_set(&fence->pending, 1);
 	fence->flags = (unsigned long)fn;
+	fence->error = 0;
 }
 
 static void __i915_sw_fence_commit(struct i915_sw_fence *fence)
@@ -254,13 +255,21 @@ void i915_sw_fence_commit(struct i915_sw_fence *fence)
 	__i915_sw_fence_commit(fence);
 }
 
-static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *key)
+static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int err, void *key)
 {
+	struct i915_sw_fence *fence = wq->private;
+
 	list_del(&wq->task_list);
-	__i915_sw_fence_complete(wq->private, key);
-	i915_sw_fence_put(wq->private);
+
+	if (err && !fence->error)
+		fence->error = err;
+
+	__i915_sw_fence_complete(fence, key);
+	i915_sw_fence_put(fence);
+
 	if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
 		kfree(wq);
+
 	return 0;
 }
 
@@ -402,6 +411,9 @@ static void timer_i915_sw_fence_wake(unsigned long data)
 	dma_fence_put(cb->dma);
 	cb->dma = NULL;
 
+	if (!cb->fence->error)
+		cb->fence->error = -ETIMEDOUT;
+
 	__i915_sw_fence_commit(cb->fence);
 	cb->timer.function = NULL;
 }
@@ -412,8 +424,11 @@ static void dma_i915_sw_fence_wake(struct dma_fence *dma,
 	struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
 
 	del_timer_sync(&cb->timer);
-	if (cb->timer.function)
+	if (cb->timer.function) {
+		if (dma->error && !cb->fence->error)
+			cb->fence->error = dma->error;
 		__i915_sw_fence_commit(cb->fence);
+	}
 	dma_fence_put(cb->dma);
 
 	kfree(cb);
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index d31cefbbcc04..b543ef2ad225 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -25,6 +25,7 @@ struct i915_sw_fence {
 	unsigned long flags;
 	struct kref kref;
 	atomic_t pending;
+	int error;
 };
 
 #define I915_SW_FENCE_CHECKED_BIT	0 /* used internally for DAG checking */
-- 
2.11.0



More information about the Intel-gfx mailing list