Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c64992e0 authored by Michel Thierry's avatar Michel Thierry Committed by Chris Wilson
Browse files

drm/i915: Look for active requests earlier in the reset path



And store the active request so that we only search for it once.

v2: Check for request completion inside _prepare_engine, don't use
ECANCELED, remove unnecessary null checks (Chris).

v3: Capture active requests during reset_prepare and store it the
engine hangcheck obj.

v4: Rename commit, change i915_gem_reset_request to just confirm the
active_request is still incomplete, instead of engine_stalled (Chris).

v5: With style; pass the active request to gem_reset_engine, keep single
return in reset_prepare_engine (Chris).

v6: Moved before reset-engine code appears (Chris)

Suggested-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v5)
Signed-off-by: default avatarMichel Thierry <michel.thierry@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170615201828.23144-2-michel.thierry@intel.com


Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170620095751.13127-3-chris@chris-wilson.co.uk
parent d5367307
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -2839,7 +2839,7 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)

	/* Ensure irq handler finishes, and not run again. */
	for_each_engine(engine, dev_priv, id) {
		struct drm_i915_gem_request *request;
		struct drm_i915_gem_request *request = NULL;

		/* Prevent the signaler thread from updating the request
		 * state (by calling dma_fence_signal) as we are processing
@@ -2871,6 +2871,8 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
			if (request && request->fence.error == -EIO)
				err = -EIO; /* Previous reset failed! */
		}

		engine->hangcheck.active_request = request;
	}

	i915_gem_revoke_fences(dev_priv);
@@ -2924,7 +2926,7 @@ static void engine_skip_context(struct drm_i915_gem_request *request)
static bool i915_gem_reset_request(struct drm_i915_gem_request *request)
{
	/* Read once and return the resolution */
	const bool guilty = engine_stalled(request->engine);
	const bool guilty = !i915_gem_request_completed(request);

	/* The guilty request will get skipped on a hung engine.
	 *
@@ -2958,11 +2960,9 @@ static bool i915_gem_reset_request(struct drm_i915_gem_request *request)
	return guilty;
}

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;

	request = i915_gem_find_active_request(engine);
	if (request && i915_gem_reset_request(request)) {
		DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n",
				 engine->name, request->global_seqno);
@@ -2988,7 +2988,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv)
	for_each_engine(engine, dev_priv, id) {
		struct i915_gem_context *ctx;

		i915_gem_reset_engine(engine);
		i915_gem_reset_engine(engine, engine->hangcheck.active_request);
		ctx = fetch_and_zero(&engine->last_retired_context);
		if (ctx)
			engine->context_unpin(engine, ctx);
@@ -3012,6 +3012,7 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
	lockdep_assert_held(&dev_priv->drm.struct_mutex);

	for_each_engine(engine, dev_priv, id) {
		engine->hangcheck.active_request = NULL;
		tasklet_enable(&engine->irq_tasklet);
		kthread_unpark(engine->breadcrumbs.signaler);
	}
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ struct intel_engine_hangcheck {
	unsigned long action_timestamp;
	int deadlock;
	struct intel_instdone instdone;
	struct drm_i915_gem_request *active_request;
	bool stalled;
};