Commit 85e97b1d authored by Matthew Brost's avatar Matthew Brost Committed by John Harrison
Browse files

drm/i915/guc: Ensure multi-lrc fini breadcrumb math is correct



Realized that the GuC multi-lrc fini breadcrumb emit code is very
delicate as the math this code does relies on functions it calls to emit
a certain number of DWs. Add a few GEM_BUG_ONs to assert the math is
correct.

v2:
  - Rebase + resend for CI
 (Checkpatch)
  - Fix blank line warning

Signed-off-by: default avatarMatthew Brost <matthew.brost@intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220119210639.33053-1-matthew.brost@intel.com
parent ff3aeb34
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -4441,27 +4441,31 @@ static inline bool skip_handshake(struct i915_request *rq)
	return test_bit(I915_FENCE_FLAG_SKIP_PARALLEL, &rq->fence.flags);
}

#define NON_SKIP_LEN	6
static u32 *
emit_fini_breadcrumb_parent_no_preempt_mid_batch(struct i915_request *rq,
						 u32 *cs)
{
	struct intel_context *ce = rq->context;
	__maybe_unused u32 *before_fini_breadcrumb_user_interrupt_cs;
	__maybe_unused u32 *start_fini_breadcrumb_cs = cs;

	GEM_BUG_ON(!intel_context_is_parent(ce));

	if (unlikely(skip_handshake(rq))) {
		/*
		 * NOP everything in __emit_fini_breadcrumb_parent_no_preempt_mid_batch,
		 * the -6 comes from the length of the emits below.
		 * the NON_SKIP_LEN comes from the length of the emits below.
		 */
		memset(cs, 0, sizeof(u32) *
		       (ce->engine->emit_fini_breadcrumb_dw - 6));
		cs += ce->engine->emit_fini_breadcrumb_dw - 6;
		       (ce->engine->emit_fini_breadcrumb_dw - NON_SKIP_LEN));
		cs += ce->engine->emit_fini_breadcrumb_dw - NON_SKIP_LEN;
	} else {
		cs = __emit_fini_breadcrumb_parent_no_preempt_mid_batch(rq, cs);
	}

	/* Emit fini breadcrumb */
	before_fini_breadcrumb_user_interrupt_cs = cs;
	cs = gen8_emit_ggtt_write(cs,
				  rq->fence.seqno,
				  i915_request_active_timeline(rq)->hwsp_offset,
@@ -4471,6 +4475,12 @@ emit_fini_breadcrumb_parent_no_preempt_mid_batch(struct i915_request *rq,
	*cs++ = MI_USER_INTERRUPT;
	*cs++ = MI_NOOP;

	/* Ensure our math for skip + emit is correct */
	GEM_BUG_ON(before_fini_breadcrumb_user_interrupt_cs + NON_SKIP_LEN !=
		   cs);
	GEM_BUG_ON(start_fini_breadcrumb_cs +
		   ce->engine->emit_fini_breadcrumb_dw != cs);

	rq->tail = intel_ring_offset(rq, cs);

	return cs;
@@ -4513,22 +4523,25 @@ emit_fini_breadcrumb_child_no_preempt_mid_batch(struct i915_request *rq,
						u32 *cs)
{
	struct intel_context *ce = rq->context;
	__maybe_unused u32 *before_fini_breadcrumb_user_interrupt_cs;
	__maybe_unused u32 *start_fini_breadcrumb_cs = cs;

	GEM_BUG_ON(!intel_context_is_child(ce));

	if (unlikely(skip_handshake(rq))) {
		/*
		 * NOP everything in __emit_fini_breadcrumb_child_no_preempt_mid_batch,
		 * the -6 comes from the length of the emits below.
		 * the NON_SKIP_LEN comes from the length of the emits below.
		 */
		memset(cs, 0, sizeof(u32) *
		       (ce->engine->emit_fini_breadcrumb_dw - 6));
		cs += ce->engine->emit_fini_breadcrumb_dw - 6;
		       (ce->engine->emit_fini_breadcrumb_dw - NON_SKIP_LEN));
		cs += ce->engine->emit_fini_breadcrumb_dw - NON_SKIP_LEN;
	} else {
		cs = __emit_fini_breadcrumb_child_no_preempt_mid_batch(rq, cs);
	}

	/* Emit fini breadcrumb */
	before_fini_breadcrumb_user_interrupt_cs = cs;
	cs = gen8_emit_ggtt_write(cs,
				  rq->fence.seqno,
				  i915_request_active_timeline(rq)->hwsp_offset,
@@ -4538,11 +4551,19 @@ emit_fini_breadcrumb_child_no_preempt_mid_batch(struct i915_request *rq,
	*cs++ = MI_USER_INTERRUPT;
	*cs++ = MI_NOOP;

	/* Ensure our math for skip + emit is correct */
	GEM_BUG_ON(before_fini_breadcrumb_user_interrupt_cs + NON_SKIP_LEN !=
		   cs);
	GEM_BUG_ON(start_fini_breadcrumb_cs +
		   ce->engine->emit_fini_breadcrumb_dw != cs);

	rq->tail = intel_ring_offset(rq, cs);

	return cs;
}

#undef NON_SKIP_LEN

static struct intel_context *
guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
		   unsigned long flags)