[Intel-gfx] [PATCH 1/3] drm/i915: Implement Selective Write workaround for Haswell GT1

Mika Kuoppala mika.kuoppala at linux.intel.com
Fri Dec 28 13:03:52 UTC 2018


Chris Wilson <chris at chris-wilson.co.uk> writes:

> From: Ben Widawsky <ben at bwidawsk.net>
>
> The docs specify this needs to be set on HSW GT1 parts. I've implemented it as
> such since it should only be needed when using RC6, but it can probably go
> anywhere.
>
> This patch fixes extremely reproducible hangs on our Jenkins setup.
>
> The interesting failure signature is:
>   IPEHR: 0x780c0000 (3DSTATE_VF)
>   INSTDONE_0: 0xffdfbffa (SVG + VS)
>
> This replaces the homebrew workaround we implemented in
>
> commit 2c550183476dfa25641309ae9a28d30feed14379
> Author: Chris Wilson <chris at chris-wilson.co.uk>
> Date:   Tue Dec 16 10:02:27 2014 +0000
>
>     drm/i915: Disable PSMI sleep messages on all rings around context switches
>
> as that is coupled into HW semaphore support which is scheduled for
> removal in the next patch.
>
> References: 2c550183476d ("drm/i915: Disable PSMI sleep messages on all rings around context switches")
> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>

Reviewed-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.h         |  2 +
>  drivers/gpu/drm/i915/i915_reg.h         |  7 ++++
>  drivers/gpu/drm/i915/intel_pm.c         | 16 +++++++-
>  drivers/gpu/drm/i915/intel_ringbuffer.c | 49 ++-----------------------
>  4 files changed, 27 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index d44255a8655e..24a5e63cc443 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2276,6 +2276,8 @@ intel_info(const struct drm_i915_private *dev_priv)
>  				 (dev_priv)->info.gt == 3)
>  #define IS_HSW_ULT(dev_priv)	(IS_HASWELL(dev_priv) && \
>  				 (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00)
> +#define IS_HSW_GT1(dev_priv)	(IS_HASWELL(dev_priv) && \
> +				 (dev_priv)->info.gt == 1)
>  #define IS_HSW_GT3(dev_priv)	(IS_HASWELL(dev_priv) && \
>  				 (dev_priv)->info.gt == 3)
>  /* ULX machines are also considered ULT. */
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 02af9b5add34..ca6a2e925194 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2464,6 +2464,13 @@ enum i915_power_well_id {
>  #define RING_DMA_FADD_UDW(base)	_MMIO((base) + 0x60) /* gen8+ */
>  #define RING_INSTPM(base)	_MMIO((base) + 0xc0)
>  #define RING_MI_MODE(base)	_MMIO((base) + 0x9c)
> +#define RING_WAIT_FOR_RC6_EXIT(base)	_MMIO((base) + 0xcc)
> +#define   RING_RC6_SEL_WRITE_ADDR_MASK		(0x7 << 4)
> +#define   RING_RC6_SEL_WRITE_ADDR_MULTICAST	(0x0 << 4)
> +#define   RING_RC6_SEL_WRITE_ADDR_UPPER_LEFT	(0x4 << 4)
> +#define   RING_RC6_SEL_WRITE_ADDR_UPPER_RIGHT	(0x5 << 4)
> +#define   RING_RC6_SEL_WRITE_ADDR_LOWER_LEFT	(0x6 << 4)
> +#define   RING_RC6_SEL_WRITE_ADDR_LOWER_RIGHT	(0x7 << 4)
>  #define INSTPS		_MMIO(0x2070) /* 965+ only */
>  #define GEN4_INSTDONE1	_MMIO(0x207c) /* 965+ only, aka INSTDONE_2 on SNB */
>  #define ACTHD_I965	_MMIO(0x2074)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 2a6ffb8b975a..c2e3502090c6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -7122,9 +7122,23 @@ static void gen6_enable_rc6(struct drm_i915_private *dev_priv)
>  	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
>  	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
>  
> -	for_each_engine(engine, dev_priv, id)
> +	for_each_engine(engine, dev_priv, id) {
>  		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
>  
> +		/*
> +		 * HSW GT1: "This field must be always [be] programmed to “100”,
> +		 * this is required to address know [sic] HW issue."
> +		 *
> +		 * Failure to do so leads to a gpu hang on context load from
> +		 * under rc6, with a characteristic IPEHR of 0x780c0000 (the
> +		 * last command from the context image).
> +		 */
> +		if (IS_HSW_GT1(dev_priv))
> +			I915_WRITE(RING_WAIT_FOR_RC6_EXIT(engine->mmio_base),
> +				   _MASKED_FIELD(RING_RC6_SEL_WRITE_ADDR_MASK,
> +						 RING_RC6_SEL_WRITE_ADDR_UPPER_LEFT));
> +	}
> +
>  	I915_WRITE(GEN6_RC_SLEEP, 0);
>  	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
>  	if (IS_IVYBRIDGE(dev_priv))
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index 65fd92eb071d..57f20033b19d 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -1602,12 +1602,6 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
>  {
>  	struct drm_i915_private *i915 = rq->i915;
>  	struct intel_engine_cs *engine = rq->engine;
> -	enum intel_engine_id id;
> -	const int num_rings =
> -		/* Use an extended w/a on gen7 if signalling from other rings */
> -		(HAS_LEGACY_SEMAPHORES(i915) && IS_GEN(i915, 7)) ?
> -		INTEL_INFO(i915)->num_rings - 1 :
> -		0;
>  	bool force_restore = false;
>  	int len;
>  	u32 *cs;
> @@ -1621,7 +1615,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
>  
>  	len = 4;
>  	if (IS_GEN(i915, 7))
> -		len += 2 + (num_rings ? 4*num_rings + 6 : 0);
> +		len += 2;
>  	if (flags & MI_FORCE_RESTORE) {
>  		GEM_BUG_ON(flags & MI_RESTORE_INHIBIT);
>  		flags &= ~MI_FORCE_RESTORE;
> @@ -1634,23 +1628,8 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
>  		return PTR_ERR(cs);
>  
>  	/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
> -	if (IS_GEN(i915, 7)) {
> +	if (IS_GEN(i915, 7))
>  		*cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
> -		if (num_rings) {
> -			struct intel_engine_cs *signaller;
> -
> -			*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
> -			for_each_engine(signaller, i915, id) {
> -				if (signaller == engine)
> -					continue;
> -
> -				*cs++ = i915_mmio_reg_offset(
> -					   RING_PSMI_CTL(signaller->mmio_base));
> -				*cs++ = _MASKED_BIT_ENABLE(
> -						GEN6_PSMI_SLEEP_MSG_DISABLE);
> -			}
> -		}
> -	}
>  
>  	if (force_restore) {
>  		/*
> @@ -1681,30 +1660,8 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
>  	 */
>  	*cs++ = MI_NOOP;
>  
> -	if (IS_GEN(i915, 7)) {
> -		if (num_rings) {
> -			struct intel_engine_cs *signaller;
> -			i915_reg_t last_reg = {}; /* keep gcc quiet */
> -
> -			*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
> -			for_each_engine(signaller, i915, id) {
> -				if (signaller == engine)
> -					continue;
> -
> -				last_reg = RING_PSMI_CTL(signaller->mmio_base);
> -				*cs++ = i915_mmio_reg_offset(last_reg);
> -				*cs++ = _MASKED_BIT_DISABLE(
> -						GEN6_PSMI_SLEEP_MSG_DISABLE);
> -			}
> -
> -			/* Insert a delay before the next switch! */
> -			*cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
> -			*cs++ = i915_mmio_reg_offset(last_reg);
> -			*cs++ = i915_scratch_offset(rq->i915);
> -			*cs++ = MI_NOOP;
> -		}
> +	if (IS_GEN(i915, 7))
>  		*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
> -	}
>  
>  	intel_ring_advance(rq, cs);
>  
> -- 
> 2.20.1


More information about the Intel-gfx mailing list