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: Matthew Brost <matthew.br...@intel.com>
Reviewed-by: John Harrison <john.c.harri...@intel.com>
---
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 33 +++++++++++++++----
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 3918f1be114f..650efd3d3a48 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -4429,27 +4429,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,
@@ -4459,6 +4463,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;
@@ -4501,22 +4511,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,
@@ -4526,11 +4539,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)
-- 
2.34.1

Reply via email to