[Intel-gfx] [PATCH 3/3] drm/i915: Disable PSMI idle messaging when stopping ring
Chris Wilson
chris at chris-wilson.co.uk
Wed Feb 27 17:14:59 UTC 2019
Quoting Mika Kuoppala (2019-02-27 16:58:50)
> Hardware cannot be in a middle of idle flow messaging
> when we pull the plug from ringbuffer. Disable idle
> messaging before we do so to avoid potential deadlock
> on engine initialization and reset.
>
> v2: INVALID_MMIO_REG, unconditional enable (Chris)
>
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Signed-off-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>
> ---
> drivers/gpu/drm/i915/intel_engine_cs.c | 56 +++++++++++++++++++++++++-
> 1 file changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index a8e47cfa6e35..fe7fca392b63 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -725,7 +725,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
>
> /**
> * intel_engines_cleanup_common - cleans up the engine state created by
> - * the common initiailizers.
> + * the common initializers.
> * @engine: Engine to cleanup.
> *
> * This cleans up everything created by the common helpers.
> @@ -826,6 +826,55 @@ void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine)
> _MASKED_BIT_DISABLE(STOP_RING));
> }
>
> +static i915_reg_t get_idle_poll_reg(const struct intel_engine_cs *engine)
> +{
> + if (engine->id != RCS)
> + return INVALID_MMIO_REG;
> +
> + if (IS_GEN(engine->i915, 9))
> + return GEN9_RCS_FE_FSM2;
> +
> + if (IS_GEN(engine->i915, 8))
> + return GEN6_RCS_PWR_FSM;
> +
> + return INVALID_MMIO_REG;
> +}
> +
> +static void disable_idle_messaging(struct intel_engine_cs *engine)
> +{
> + struct drm_i915_private *dev_priv = engine->i915;
> + i915_reg_t poll_reg;
> +
> + poll_reg = get_idle_poll_reg(engine);
> + if (!i915_mmio_reg_valid(poll_reg))
> + return;
> +
> + GEM_DEBUG_WARN_ON(I915_READ_FW(GEN6_RC_SLEEP_PSMI_CONTROL) &
> + GEN6_PSMI_SLEEP_MSG_DISABLE);
> +
> + I915_WRITE_FW(GEN6_RC_SLEEP_PSMI_CONTROL,
> + _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> +
Needs some reference at least. Or a synposis of what exactly we are
waiting for in a comment.
> + if (__intel_wait_for_register_fw(dev_priv, poll_reg,
> + 0x7f, 0x30,
> + 5000, 0,
> + NULL))
> + DRM_DEBUG_DRIVER("psmi idle msg poll timeout\n");
> +}
> +
> +static void enable_idle_messaging(struct intel_engine_cs *engine)
> +{
> + struct drm_i915_private *dev_priv = engine->i915;
> + i915_reg_t poll_reg;
> +
> + poll_reg = get_idle_poll_reg(engine);
> + if (!i915_mmio_reg_valid(poll_reg))
> + return;
> +
> + I915_WRITE_FW(GEN6_RC_SLEEP_PSMI_CONTROL,
> + _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> +}
> +
> int intel_engine_stop_ringbuffer(struct intel_engine_cs *engine)
> {
> struct drm_i915_private *dev_priv = engine->i915;
> @@ -841,9 +890,14 @@ int intel_engine_stop_ringbuffer(struct intel_engine_cs *engine)
> I915_WRITE_FW(RING_TAIL(base), 0);
> POSTING_READ_FW(RING_TAIL(base));
>
> + /* Idle messaging needs to be off during ring disable */
> + disable_idle_messaging(engine);
> +
> /* The ring must be empty before it is disabled */
> I915_WRITE_FW(RING_CTL(base), 0);
>
> + enable_idle_messaging(engine);
> +
> /* Check acts as a post */
> if (I915_READ_FW(RING_HEAD(base))) {
> GEM_TRACE("%s: ring head [%x] not parked\n",
Given the history SLEEP_MSG_DISABLE around RING_CTL is not surprising.
Acked-by: Chris Wilson <chris at chris-wilson.co.uk>
-Chris
More information about the Intel-gfx
mailing list