> -----Original Message-----
> From: Vivi, Rodrigo
> Sent: Friday, April 10, 2015 12:50 PM
> To: intel-gfx@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 <b...@bwidawsk.net>
> Cc: U. Artie Eoff <ullysses.a.e...@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.v...@intel.com>

Tested-by: U. Artie Eoff <ullysses.a.e...@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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to