[Intel-gfx] [PATCH] drm/i915: Force HW context restore on resume.
Eoff, Ullysses A
ullysses.a.eoff at intel.com
Fri Apr 10 13:04:28 PDT 2015
> -----Original Message-----
> From: Vivi, Rodrigo
> Sent: Friday, April 10, 2015 12:50 PM
> To: intel-gfx at lists.freedesktop.org
> Cc: Vivi, Rodrigo; Ben Widawsky; Eoff, Ullysses A
> Subject: [PATCH] drm/i915: Force HW context restore on resume.
>
> Using aliasing ppgtt in some cases like playing video the GPU might hang
> because HW context was not in a reliable state.
> When we resume we switch to default context and when we resume we can
> force a restore if default is really there and object is bound.
>
> Cc: Ben Widawsky <ben at bwidawsk.net>
> Cc: U. Artie Eoff <ullysses.a.eoff at intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
Tested-by: U. Artie Eoff <ullysses.a.eoff at intel.com>
> ---
> drivers/gpu/drm/i915/i915_gem_context.c | 180 +++++++++++++++++---------------
> 1 file changed, 94 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index e4c57a3..0a8a07a 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -97,6 +97,91 @@
> #define GEN6_CONTEXT_ALIGN (64<<10)
> #define GEN7_CONTEXT_ALIGN 4096
>
> +static inline int
> +mi_set_context(struct intel_engine_cs *ring,
> + struct intel_context *new_context,
> + u32 hw_flags)
> +{
> + u32 flags = hw_flags | MI_MM_SPACE_GTT;
> + const int num_rings =
> + /* Use an extended w/a on ivb+ if signalling from other rings */
> + i915_semaphore_is_enabled(ring->dev) ?
> + hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 :
> + 0;
> + int len, i, ret;
> +
> + /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
> + * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
> + * explicitly, so we rely on the value at ring init, stored in
> + * itlb_before_ctx_switch.
> + */
> + if (IS_GEN6(ring->dev)) {
> + ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0);
> + if (ret)
> + return ret;
> + }
> +
> + /* These flags are for resource streamer on HSW+ */
> + if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8)
> + flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN);
> +
> +
> + len = 4;
> + if (INTEL_INFO(ring->dev)->gen >= 7)
> + len += 2 + (num_rings ? 4*num_rings + 2 : 0);
> +
> + ret = intel_ring_begin(ring, len);
> + if (ret)
> + return ret;
> +
> + /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
> + if (INTEL_INFO(ring->dev)->gen >= 7) {
> + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
> + if (num_rings) {
> + struct intel_engine_cs *signaller;
> +
> + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
> + for_each_ring(signaller, to_i915(ring->dev), i) {
> + if (signaller == ring)
> + continue;
> +
> + intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
> + intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> + }
> + }
> + }
> +
> + intel_ring_emit(ring, MI_NOOP);
> + intel_ring_emit(ring, MI_SET_CONTEXT);
> + intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) |
> + flags);
> + /*
> + * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
> + * WaMiSetContext_Hang:snb,ivb,vlv
> + */
> + intel_ring_emit(ring, MI_NOOP);
> +
> + if (INTEL_INFO(ring->dev)->gen >= 7) {
> + if (num_rings) {
> + struct intel_engine_cs *signaller;
> +
> + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
> + for_each_ring(signaller, to_i915(ring->dev), i) {
> + if (signaller == ring)
> + continue;
> +
> + intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
> + intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> + }
> + }
> + intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
> + }
> +
> + intel_ring_advance(ring);
> +
> + return ret;
> +}
> +
> static size_t get_context_alignment(struct drm_device *dev)
> {
> if (IS_GEN6(dev))
> @@ -412,6 +497,7 @@ void i915_gem_context_fini(struct drm_device *dev)
> int i915_gem_context_enable(struct drm_i915_private *dev_priv)
> {
> struct intel_engine_cs *ring;
> + struct intel_context *lctx = dev_priv->ring[RCS].last_context;
> int ret, i;
>
> BUG_ON(!dev_priv->ring[RCS].default_context);
> @@ -429,12 +515,19 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
> }
> }
>
> - } else
> + } else {
> for_each_ring(ring, dev_priv, i) {
> ret = i915_switch_context(ring, ring->default_context);
> if (ret)
> return ret;
> }
> + /* Force default HW Context restore on Resume */
> + if (lctx == dev_priv->ring[RCS].default_context &&
> + i915_gem_obj_ggtt_bound(lctx->legacy_hw_ctx.rcs_state)) {
> + mi_set_context(&dev_priv->ring[RCS], lctx,
> + MI_FORCE_RESTORE | MI_SAVE_EXT_STATE_EN);
> + }
> + }
>
> return 0;
> }
> @@ -486,91 +579,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
> return ctx;
> }
>
> -static inline int
> -mi_set_context(struct intel_engine_cs *ring,
> - struct intel_context *new_context,
> - u32 hw_flags)
> -{
> - u32 flags = hw_flags | MI_MM_SPACE_GTT;
> - const int num_rings =
> - /* Use an extended w/a on ivb+ if signalling from other rings */
> - i915_semaphore_is_enabled(ring->dev) ?
> - hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 :
> - 0;
> - int len, i, ret;
> -
> - /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
> - * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
> - * explicitly, so we rely on the value at ring init, stored in
> - * itlb_before_ctx_switch.
> - */
> - if (IS_GEN6(ring->dev)) {
> - ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0);
> - if (ret)
> - return ret;
> - }
> -
> - /* These flags are for resource streamer on HSW+ */
> - if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8)
> - flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN);
> -
> -
> - len = 4;
> - if (INTEL_INFO(ring->dev)->gen >= 7)
> - len += 2 + (num_rings ? 4*num_rings + 2 : 0);
> -
> - ret = intel_ring_begin(ring, len);
> - if (ret)
> - return ret;
> -
> - /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
> - if (INTEL_INFO(ring->dev)->gen >= 7) {
> - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
> - if (num_rings) {
> - struct intel_engine_cs *signaller;
> -
> - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
> - for_each_ring(signaller, to_i915(ring->dev), i) {
> - if (signaller == ring)
> - continue;
> -
> - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
> - intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> - }
> - }
> - }
> -
> - intel_ring_emit(ring, MI_NOOP);
> - intel_ring_emit(ring, MI_SET_CONTEXT);
> - intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) |
> - flags);
> - /*
> - * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
> - * WaMiSetContext_Hang:snb,ivb,vlv
> - */
> - intel_ring_emit(ring, MI_NOOP);
> -
> - if (INTEL_INFO(ring->dev)->gen >= 7) {
> - if (num_rings) {
> - struct intel_engine_cs *signaller;
> -
> - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
> - for_each_ring(signaller, to_i915(ring->dev), i) {
> - if (signaller == ring)
> - continue;
> -
> - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
> - intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
> - }
> - }
> - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
> - }
> -
> - intel_ring_advance(ring);
> -
> - return ret;
> -}
> -
> static inline bool should_skip_switch(struct intel_engine_cs *ring,
> struct intel_context *from,
> struct intel_context *to)
> --
> 2.1.0
More information about the Intel-gfx
mailing list