[PATCH 19/20] drm/i915: drm/i915 changes to simulated hangs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Tim Gore <tim.gore@xxxxxxxxx>

Simulated hangs, as used by drv_hangman and some other IGT tests, are not
handled correctly with the new per-engine hang recovery mode. This patch fixes
several issues needed to get them working in the execlist case.

1) The "simulated" hang is effected by not submitting a particular batch buffer
   to the hardware. In this way it is not handled by the hardware are hence
   remains in the software queue, leading the TDR mechanism to declare a hang.
   The place where the submission of the batch was being blocked was in
   intel_logical_ring_advance_and_submit. Because this means the request never
   enters the execlist_queue, the TDR mechanism does not detect a hang and the
   situation is never cleared. Also, blocking the batch buffer here is before
   the intel_ctx_submit_request object gets allocated. During TDR we need to
   actually complete the submission process to unhang the ring, but we are not
   in user context so cannot allocate the request object.  To overcome both
   these issues I moved the place where submission is blocked to
   execlists_context_unqueue. This means that the request enters the
   ring->execlist_queue, so the TDR mechanism detects the hang and can resubmit
   the request after the stop_rings bit is cleared.

2) A further problem arises from a workaround in i915_hangcheck_sample to deal
   with a context submission status of "...INCONSISTENT" being reported by
   intel_execlists_TDR_get_current_request() when the hardware is idle.  A
   simulated hang, because it causes the sw and hw context id's to be out of
   sync, results in a context submission status of "...INCONSISTENT" being
   reported, triggering this workaround which resubmits the batch and clears
   the hang, avoiding a ring reset. But we want the ring reset to occur, since
   this is part of what we are testing. So, I have made
   intel_execlists_TDR_get_current_request() aware of simulated hangs, so that
   it returns a status of OK in this case.  This avoids the workaround being
   triggered, leading to the TDR mechanism declaring a ring hang and doing a
   ring reset.

Issue: VIZ-5488
Signed-off-by: Tim Gore <tim.gore@xxxxxxxxx>
Signed-off-by: Tomas Elf <tomas.elf@xxxxxxxxx>
---
 drivers/gpu/drm/i915/i915_drv.c  | 10 ++++++++++
 drivers/gpu/drm/i915/intel_lrc.c | 26 +++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 73976f9..fd51c26 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1167,6 +1167,16 @@ int i915_reset_engine(struct intel_engine_cs *engine)
 		 }
 	}
 
+	/* Clear any simulated hang flags */
+	if (dev_priv->gpu_error.stop_rings) {
+		DRM_INFO("Simulated gpu hang, reset stop_rings bits %08x\n",
+			(0x1 << engine->id));
+		dev_priv->gpu_error.stop_rings &= ~(0x1 << engine->id);
+		/* if all hangs are cleared, then clear the ALLOW_BAN/ERROR bits */
+		if ((dev_priv->gpu_error.stop_rings & ((1 << I915_NUM_RINGS) - 1)) == 0)
+			dev_priv->gpu_error.stop_rings = 0;
+	}
+
 	/* Sample the current ring head position */
 	head = I915_READ_HEAD(engine) & HEAD_ADDR;
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 85107a1..b565d78 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -653,6 +653,16 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring, bool tdr_res
 		}
 	}
 
+	/* Check for a simulated hang request */
+	if (intel_ring_stopped(ring)) {
+		/*
+		 * Mark the request at the head of the queue as submitted but
+		 * dont actually submit it.
+		 */
+		req0->elsp_submitted++;
+		return;
+	}
+
 	WARN_ON(req1 && req1->elsp_submitted && !tdr_resubmission);
 
 	execlists_submit_requests(req0, req1, tdr_resubmission);
@@ -1045,16 +1055,12 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
 static void
 intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
 {
-	struct intel_engine_cs *ring = request->ring;
 	struct drm_i915_private *dev_priv = request->i915;
 
 	intel_logical_ring_advance(request->ringbuf);
 
 	request->tail = request->ringbuf->tail;
 
-	if (intel_ring_stopped(ring))
-		return;
-
 	if (dev_priv->guc.execbuf_client)
 		i915_guc_submit(dev_priv->guc.execbuf_client, request);
 	else
@@ -3290,7 +3296,17 @@ intel_execlists_TDR_get_current_request(struct intel_engine_cs *ring,
 	}
 
 	if (tmpctx) {
-		status = ((hw_context == sw_context) && hw_active) ?
+		/*
+		 * Check for simuated hang. In this case the head entry in the
+		 * sw execlist queue will not have been submitted to the ELSP, so
+		 * the hw and sw context id's may well disagree, but we still want
+		 * to proceed with hang recovery. So we return OK which allows
+		 * the TDR recovery mechanism to proceed with a ring reset.
+		 */
+		if (intel_ring_stopped(ring))
+			status = CONTEXT_SUBMISSION_STATUS_OK;
+		else
+			status = ((hw_context == sw_context) && hw_active) ?
 				CONTEXT_SUBMISSION_STATUS_OK :
 				CONTEXT_SUBMISSION_STATUS_INCONSISTENT;
 	} else {
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux