Commit 7ec73b7e authored by Chris Wilson's avatar Chris Wilson

drm/i915: Only skip requests once a context is banned

If we skip before banning, we have an inconsistent interface between
execbuf still queueing valid request but those requests already queued
being cancelled. If we only cancel the pending requests once we stop
accepting new requests, the user interface is more consistent.
Reported-by: default avatarTvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Fixes: 821ed7df ("drm/i915: Update reset path to fix incomplete requests")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: <stable@vger.kernel.org> # v4.9+
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170105170059.344-1-chris@chris-wilson.co.uk
parent b7163936
...@@ -2734,7 +2734,7 @@ void i915_gem_reset_prepare(struct drm_i915_private *dev_priv) ...@@ -2734,7 +2734,7 @@ void i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
static void i915_gem_reset_engine(struct intel_engine_cs *engine) static void i915_gem_reset_engine(struct intel_engine_cs *engine)
{ {
struct drm_i915_gem_request *request; struct drm_i915_gem_request *request;
struct i915_gem_context *incomplete_ctx; struct i915_gem_context *hung_ctx;
struct intel_timeline *timeline; struct intel_timeline *timeline;
unsigned long flags; unsigned long flags;
bool ring_hung; bool ring_hung;
...@@ -2746,6 +2746,8 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) ...@@ -2746,6 +2746,8 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
if (!request) if (!request)
return; return;
hung_ctx = request->ctx;
ring_hung = engine->hangcheck.stalled; ring_hung = engine->hangcheck.stalled;
if (engine->hangcheck.seqno != intel_engine_get_seqno(engine)) { if (engine->hangcheck.seqno != intel_engine_get_seqno(engine)) {
DRM_DEBUG_DRIVER("%s pardoned, was guilty? %s\n", DRM_DEBUG_DRIVER("%s pardoned, was guilty? %s\n",
...@@ -2755,9 +2757,9 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) ...@@ -2755,9 +2757,9 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
} }
if (ring_hung) if (ring_hung)
i915_gem_context_mark_guilty(request->ctx); i915_gem_context_mark_guilty(hung_ctx);
else else
i915_gem_context_mark_innocent(request->ctx); i915_gem_context_mark_innocent(hung_ctx);
if (!ring_hung) if (!ring_hung)
return; return;
...@@ -2768,6 +2770,10 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) ...@@ -2768,6 +2770,10 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
/* Setup the CS to resume from the breadcrumb of the hung request */ /* Setup the CS to resume from the breadcrumb of the hung request */
engine->reset_hw(engine, request); engine->reset_hw(engine, request);
/* If this context is now banned, skip all of its pending requests. */
if (!i915_gem_context_is_banned(hung_ctx))
return;
/* Users of the default context do not rely on logical state /* Users of the default context do not rely on logical state
* preserved between batches. They have to emit full state on * preserved between batches. They have to emit full state on
* every batch and so it is safe to execute queued requests following * every batch and so it is safe to execute queued requests following
...@@ -2776,17 +2782,16 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) ...@@ -2776,17 +2782,16 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
* Other contexts preserve state, now corrupt. We want to skip all * Other contexts preserve state, now corrupt. We want to skip all
* queued requests that reference the corrupt context. * queued requests that reference the corrupt context.
*/ */
incomplete_ctx = request->ctx; if (i915_gem_context_is_default(hung_ctx))
if (i915_gem_context_is_default(incomplete_ctx))
return; return;
timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine); timeline = i915_gem_context_lookup_timeline(hung_ctx, engine);
spin_lock_irqsave(&engine->timeline->lock, flags); spin_lock_irqsave(&engine->timeline->lock, flags);
spin_lock(&timeline->lock); spin_lock(&timeline->lock);
list_for_each_entry_continue(request, &engine->timeline->requests, link) list_for_each_entry_continue(request, &engine->timeline->requests, link)
if (request->ctx == incomplete_ctx) if (request->ctx == hung_ctx)
reset_request(request); reset_request(request);
list_for_each_entry(request, &timeline->requests, link) list_for_each_entry(request, &timeline->requests, link)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment