[PATCH 3/3] order
Chris Wilson
chris at chris-wilson.co.uk
Mon Mar 5 10:29:47 UTC 2018
---
drivers/gpu/drm/i915/i915_gem.c | 66 +++++++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 8d913d833ab9..24d483da2695 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3265,6 +3265,52 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
wake_up_all(&i915->gpu_error.reset_queue);
}
+static bool __wait_for_wedge(struct intel_timeline *timeline)
+{
+ do {
+ struct i915_request *rq;
+ unsigned long flags;
+ bool err;
+
+ /*
+ * During wedging we can not rely on the timelines being
+ * monotonic, i915_gem_set_wedge() may result in the
+ * requests being added to the execution timeline in a
+ * different order than on the client's timeline and so
+ * be signalled out-of-order. To compensate, we check evey
+ * request on the timeline and wait for them all to be
+ * signalled.
+ */
+ spin_lock_irqsave(&timeline->lock, flags);
+ list_for_each_entry(rq, &timeline->requests, link) {
+ if (!dma_fence_is_signaled(&rq->fence)) {
+ i915_request_get(rq);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&timeline->lock, flags);
+ if (!rq)
+ return true;
+
+ /*
+ * We can't use our normal waiter as we want to
+ * avoid recursively trying to handle the current
+ * reset. The basic dma_fence_default_wait() installs
+ * a callback for dma_fence_signal(), which is
+ * triggered by our nop handler (indirectly, the
+ * callback enables the signaler thread which is
+ * woken by the nop_submit_request() advancing the seqno
+ * and when the seqno passes the fence, the signaler
+ * then signals the fence waking us up).
+ */
+ err = dma_fence_default_wait(&rq->fence, true,
+ MAX_SCHEDULE_TIMEOUT) < 0;
+ i915_request_put(rq);
+ if (err)
+ return false;
+ } while (1);
+}
+
bool i915_gem_unset_wedged(struct drm_i915_private *i915)
{
struct i915_gem_timeline *tl;
@@ -3285,25 +3331,7 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915)
*/
list_for_each_entry(tl, &i915->gt.timelines, link) {
for (i = 0; i < ARRAY_SIZE(tl->engine); i++) {
- struct i915_request *rq;
-
- rq = i915_gem_active_peek(&tl->engine[i].last_request,
- &i915->drm.struct_mutex);
- if (!rq)
- continue;
-
- /* We can't use our normal waiter as we want to
- * avoid recursively trying to handle the current
- * reset. The basic dma_fence_default_wait() installs
- * a callback for dma_fence_signal(), which is
- * triggered by our nop handler (indirectly, the
- * callback enables the signaler thread which is
- * woken by the nop_submit_request() advancing the seqno
- * and when the seqno passes the fence, the signaler
- * then signals the fence waking us up).
- */
- if (dma_fence_default_wait(&rq->fence, true,
- MAX_SCHEDULE_TIMEOUT) < 0)
+ if (!__wait_for_wedge(&tl->engine[i]))
return false;
}
}
--
2.16.2
More information about the Intel-gfx-trybot
mailing list