[Intel-gfx] [PATCH 2/2] drm/i915/execlists: Delay writing to ELSP until HW has processed the previous write
Chris Wilson
chris at chris-wilson.co.uk
Sat Nov 18 16:36:43 UTC 2017
Quoting Chris Wilson (2017-11-18 11:25:32)
> The hardware needs some time to process the information received in the
> ExecList Submission Port, and expects us to don't write anything new until
> it has 'acknowledged' this new execlist by sending an IDLE_ACTIVE or
> PREEMPTED CSB event.
>
> If we do not follow this, the driver could write new data into the ELSP
> before HW had finishing fetching the previous one, putting us in
> 'undefined behaviour' space.
>
> This seems to be the problem causing the spurious PREEMPTED & COMPLETE
> events after a COMPLETE like the one below:
>
> [] vcs0: sw rd pointer = 2, hw wr pointer = 0, current 'head' = 3.
> [] vcs0: Execlist CSB[0]: 0x00000018 _ 0x00000007
> [] vcs0: Execlist CSB[1]: 0x00000001 _ 0x00000000
> [] vcs0: Execlist CSB[2]: 0x00000018 _ 0x00000007 <<< COMPLETE
> [] vcs0: Execlist CSB[3]: 0x00000012 _ 0x00000007 <<< PREEMPTED & COMPLETE
> [] vcs0: Execlist CSB[4]: 0x00008002 _ 0x00000006
> [] vcs0: Execlist CSB[5]: 0x00000014 _ 0x00000006
>
> The ELSP writes that lead to this CSB sequence show that the HW hadn't
> started executing the previous execlist (the one with only ctx 0x6) by the
> time the new one was submitted; this is a bit more clear in the data
> show in the EXECLIST_STATUS register at the time of the ELSP write.
>
> [] vcs0: ELSP[0] = 0x0_0 [execlist1] - status_reg = 0x0_302
> [] vcs0: ELSP[1] = 0x6_fedb2119 [execlist0] - status_reg = 0x0_8302
>
> [] vcs0: ELSP[2] = 0x7_fedaf119 [execlist1] - status_reg = 0x0_8308
> [] vcs0: ELSP[3] = 0x6_fedb2119 [execlist0] - status_reg = 0x7_8308
>
> Note that having to wait for this ack does not disable lite-restores,
> although it may reduce their numbers.
>
> v2: Rewrote Michel's patch, his digging and his fix, my spelling.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102035
> Suggested-by: Michel Thierry <michel.thierry at intel.com>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Michel Thierry <michel.thierry at intel.com>
> ---
> drivers/gpu/drm/i915/intel_lrc.c | 25 +++++++++++++++++++++++--
> drivers/gpu/drm/i915/intel_ringbuffer.h | 1 +
> 2 files changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index c2cfdfdc0722..2694bc40f0fe 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -479,6 +479,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine)
>
> elsp_write(desc, elsp);
> }
> + execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK);
> }
>
> static bool ctx_single_port_submission(const struct i915_gem_context *ctx)
> @@ -531,6 +532,7 @@ static void inject_preempt_context(struct intel_engine_cs *engine)
> elsp_write(0, elsp);
>
> elsp_write(ce->lrc_desc, elsp);
> + execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK);
> }
>
> static void execlists_dequeue(struct intel_engine_cs *engine)
> @@ -577,9 +579,20 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
> * know the next preemption status we see corresponds
> * to this ELSP update.
> */
> + GEM_BUG_ON(!port_count(&port[0]));
> if (port_count(&port[0]) > 1)
> goto unlock;
>
> + /*
> + * If we write to ELSP a second time before the HW has had
> + * a chance to respond to the previous write, we can confuse
> + * the HW and hit "undefined behaviour". After writing to ELSP,
> + * we must then wait until we see a context-switch event from
> + * the HW to indicate that it has had a chance to respond.
> + */
> + if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK))
> + goto unlock;
> +
> if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) &&
> rb_entry(rb, struct i915_priolist, node)->priority >
> max(last->priotree.priority, 0)) {
> @@ -876,6 +889,15 @@ static void execlists_submission_tasklet(unsigned long data)
> if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK))
> continue;
>
> + /*
> + * Note that we could acknowledge the first IDLE_ACTIVE
> + * event as the HW having processed the first ELSP
> + * write, we just choose not to for simplicity. Once
> + * a flow is established, lite-restore events provide
> + * us with the acks we need.
> + */
> + execlists_set_active(execlists, EXECLISTS_ACTIVE_HWACK);
On second thought, and thankfully we already have tests to demonstrate
this, we do need to respond to IDLE_ACTIVE to allow preemption on the
first submit.
As to the assert hit during gem_exec_schedule, that is another question.
-Chris
More information about the Intel-gfx
mailing list