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

Commit 519a0194 authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915/hangcheck: Replace hangcheck.seqno with RING_HEAD



After realising we need to sample RING_START to detect context switches
from preemption events that do not allow for the seqno to advance, we
can also realise that the seqno itself is just a distance along the ring
and so can be replaced by sampling RING_HEAD.

v2: Bonus comment for the mystery separate CS_STALL before MI_USER_INTERRUPT

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190508080704.24223-1-chris@chris-wilson.co.uk
parent 18ecc6c5
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -215,8 +215,6 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
 */
#define I915_GEM_HWS_PREEMPT		0x32
#define I915_GEM_HWS_PREEMPT_ADDR	(I915_GEM_HWS_PREEMPT * sizeof(u32))
#define I915_GEM_HWS_HANGCHECK		0x34
#define I915_GEM_HWS_HANGCHECK_ADDR	(I915_GEM_HWS_HANGCHECK * sizeof(u32))
#define I915_GEM_HWS_SEQNO		0x40
#define I915_GEM_HWS_SEQNO_ADDR		(I915_GEM_HWS_SEQNO * sizeof(u32))
#define I915_GEM_HWS_SCRATCH		0x80
@@ -548,17 +546,4 @@ static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)

#endif

static inline u32
intel_engine_next_hangcheck_seqno(struct intel_engine_cs *engine)
{
	return engine->hangcheck.next_seqno =
		next_pseudo_random32(engine->hangcheck.next_seqno);
}

static inline u32
intel_engine_get_hangcheck_seqno(struct intel_engine_cs *engine)
{
	return intel_read_status_page(engine, I915_GEM_HWS_HANGCHECK);
}

#endif /* _INTEL_RINGBUFFER_H_ */
+2 −3
Original line number Diff line number Diff line
@@ -721,6 +721,7 @@ static int measure_breadcrumb_dw(struct intel_engine_cs *engine)
		goto out_timeline;

	dw = engine->emit_fini_breadcrumb(&frame->rq, frame->cs) - frame->cs;
	GEM_BUG_ON(dw & 1); /* RING_TAIL must be qword aligned */

	i915_timeline_unpin(&frame->timeline);

@@ -1444,9 +1445,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
		drm_printf(m, "*** WEDGED ***\n");

	drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count));
	drm_printf(m, "\tHangcheck %x:%x [%d ms]\n",
		   engine->hangcheck.last_seqno,
		   engine->hangcheck.next_seqno,
	drm_printf(m, "\tHangcheck: %d ms ago\n",
		   jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp));
	drm_printf(m, "\tReset count: %d (global %d)\n",
		   i915_reset_engine_count(error, engine),
+1 −2
Original line number Diff line number Diff line
@@ -54,8 +54,7 @@ struct intel_instdone {
struct intel_engine_hangcheck {
	u64 acthd;
	u32 last_ring;
	u32 last_seqno;
	u32 next_seqno;
	u32 last_head;
	unsigned long action_timestamp;
	struct intel_instdone instdone;
};
+4 −4
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@
struct hangcheck {
	u64 acthd;
	u32 ring;
	u32 seqno;
	u32 head;
	enum intel_engine_hangcheck_action action;
	unsigned long action_timestamp;
	int deadlock;
@@ -134,16 +134,16 @@ static void hangcheck_load_sample(struct intel_engine_cs *engine,
				  struct hangcheck *hc)
{
	hc->acthd = intel_engine_get_active_head(engine);
	hc->seqno = intel_engine_get_hangcheck_seqno(engine);
	hc->ring = ENGINE_READ(engine, RING_START);
	hc->head = ENGINE_READ(engine, RING_HEAD);
}

static void hangcheck_store_sample(struct intel_engine_cs *engine,
				   const struct hangcheck *hc)
{
	engine->hangcheck.acthd = hc->acthd;
	engine->hangcheck.last_seqno = hc->seqno;
	engine->hangcheck.last_ring = hc->ring;
	engine->hangcheck.last_head = hc->head;
}

static enum intel_engine_hangcheck_action
@@ -156,7 +156,7 @@ hangcheck_get_action(struct intel_engine_cs *engine,
	if (engine->hangcheck.last_ring != hc->ring)
		return ENGINE_ACTIVE_SEQNO;

	if (engine->hangcheck.last_seqno != hc->seqno)
	if (engine->hangcheck.last_head != hc->head)
		return ENGINE_ACTIVE_SEQNO;

	return engine_stuck(engine, hc->acthd);
+6 −14
Original line number Diff line number Diff line
@@ -2275,12 +2275,6 @@ static u32 *gen8_emit_fini_breadcrumb(struct i915_request *request, u32 *cs)
				  request->timeline->hwsp_offset,
				  0);

	cs = gen8_emit_ggtt_write(cs,
				  intel_engine_next_hangcheck_seqno(request->engine),
				  I915_GEM_HWS_HANGCHECK_ADDR,
				  MI_FLUSH_DW_STORE_INDEX);


	*cs++ = MI_USER_INTERRUPT;
	*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;

@@ -2292,19 +2286,17 @@ static u32 *gen8_emit_fini_breadcrumb(struct i915_request *request, u32 *cs)

static u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
{
	/* XXX flush+write+CS_STALL all in one upsets gem_concurrent_blt:kbl */
	cs = gen8_emit_ggtt_write_rcs(cs,
				      request->fence.seqno,
				      request->timeline->hwsp_offset,
				      PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
				      PIPE_CONTROL_DEPTH_CACHE_FLUSH |
				      PIPE_CONTROL_DC_FLUSH_ENABLE |
				      PIPE_CONTROL_DC_FLUSH_ENABLE);
	cs = gen8_emit_pipe_control(cs,
				    PIPE_CONTROL_FLUSH_ENABLE |
				      PIPE_CONTROL_CS_STALL);

	cs = gen8_emit_ggtt_write_rcs(cs,
				      intel_engine_next_hangcheck_seqno(request->engine),
				      I915_GEM_HWS_HANGCHECK_ADDR,
				      PIPE_CONTROL_STORE_DATA_INDEX);
				    PIPE_CONTROL_CS_STALL,
				    0);

	*cs++ = MI_USER_INTERRUPT;
	*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
Loading