[FOR_CI_v5 06/13] drm/i915/tdr: Identify hung request and drop it

Arun Siluvery arun.siluvery at linux.intel.com
Wed Jul 13 14:33:49 UTC 2016


The current active request is the one that caused the hang so this is
retrieved and removed from elsp queue, otherwise we cannot submit other
workloads to be processed by GPU.

A consistency check between HW and driver is performed to ensure that we
are dropping the correct request. Since this request doesn't get executed
anymore, we also need to advance the seqno to mark it as complete.

Signed-off-by: Arun Siluvery <arun.siluvery at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_lrc.c | 72 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_lrc.h |  3 ++
 2 files changed, 75 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 70c6990..80a6c30 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1029,6 +1029,78 @@ void intel_lr_context_unpin(struct i915_gem_context *ctx,
 	i915_gem_context_unreference(ctx);
 }
 
+/**
+ * intel_execlists_reset_prepare() - identifies the request that is
+ * hung and drops it
+ *
+ * Head is adjusted to the start of next request.
+ *
+ * @engine: Engine that is currently hung
+ *
+ * Returns:
+ *   0 - on success
+ *   nonzero errorcode otherwise
+ */
+int intel_execlists_reset_prepare(struct intel_engine_cs *engine)
+{
+	struct drm_i915_gem_request *req;
+	int ret = -EINVAL;
+
+	req = i915_gem_find_active_request(engine);
+	if (!req)
+		return -EINVAL;
+
+	spin_lock_bh(&engine->execlist_lock);
+	/*
+	 * Only acknowledge the request in the execlist queue if it's actually
+	 * been submitted to hardware, otherwise there's the risk of
+	 * inconsistency between the (unsubmitted) request and the idle
+	 * hardware state.
+	 */
+	if (req->ctx && req->elsp_submitted) {
+		u32 execlist_status;
+		u32 hw_context;
+		u32 hw_active;
+		struct drm_i915_private *dev_priv = engine->i915;
+
+		hw_context = I915_READ(RING_EXECLIST_STATUS_CTX_ID(engine));
+		execlist_status = I915_READ(RING_EXECLIST_STATUS_LO(engine));
+		hw_active = ((execlist_status & EXECLIST_STATUS_ELEMENT0_ACTIVE) ||
+			     (execlist_status & EXECLIST_STATUS_ELEMENT1_ACTIVE));
+
+		if (hw_active && hw_context == req->ctx->hw_id) {
+			uint32_t *reg_state;
+			/*
+			 * GPU is now hung and the request that caused it
+			 * will be dropped so mark it as completed
+			 */
+			intel_write_status_page(engine, I915_GEM_HWS_INDEX, req->seqno);
+
+			/* advance the head to the start of the next request */
+			reg_state = req->ctx->engine[engine->id].lrc_reg_state;
+			reg_state[CTX_RING_HEAD+1] = req->postfix;
+
+			/*
+			 * remove the request from the elsp queue so that
+			 * engine can resume execution after reset when new
+			 * requests are submitted
+			 */
+			if (!--req->elsp_submitted) {
+				list_del(&req->execlist_link);
+				i915_gem_request_unreference(req);
+			}
+			ret = 0;
+		} else {
+			DRM_ERROR("HW in inconsistent state, hw_active=%u\n", hw_active);
+		}
+	}else {
+		WARN(1, "Invalid request\n");
+	}
+
+	spin_unlock_bh(&engine->execlist_lock);
+	return ret;
+}
+
 static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
 	int ret, i;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 2b8255c..9f81bbe 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -31,7 +31,10 @@
 /* Execlists regs */
 #define RING_ELSP(ring)				_MMIO((ring)->mmio_base + 0x230)
 #define RING_EXECLIST_STATUS_LO(ring)		_MMIO((ring)->mmio_base + 0x234)
+#define   EXECLIST_STATUS_ELEMENT0_ACTIVE       (1 << 14)
+#define   EXECLIST_STATUS_ELEMENT1_ACTIVE       (1 << 15)
 #define RING_EXECLIST_STATUS_HI(ring)		_MMIO((ring)->mmio_base + 0x234 + 4)
+#define RING_EXECLIST_STATUS_CTX_ID(ring)RING_EXECLIST_STATUS_HI(ring)
 #define RING_CONTEXT_CONTROL(ring)		_MMIO((ring)->mmio_base + 0x244)
 #define	  CTX_CTRL_INHIBIT_SYN_CTX_SWITCH	(1 << 3)
 #define	  CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT	(1 << 0)
-- 
1.9.1



More information about the Intel-gfx-trybot mailing list