> -----Original Message----- > From: Vivi, Rodrigo > Sent: Friday, April 10, 2015 12:50 PM > To: intel-gfx@xxxxxxxxxxxxxxxxxxxxx > 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@xxxxxxxxxxxx> > Cc: U. Artie Eoff <ullysses.a.eoff@xxxxxxxxx> > Signed-off-by: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> Tested-by: U. Artie Eoff <ullysses.a.eoff@xxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx