[Intel-gfx] [PATCH] drm/i915: Workaround async flip + VT-d corruption on HSW/BDW
Karthik B S
karthik.b.s at intel.com
Fri Mar 12 10:24:08 UTC 2021
On 2/20/2021 4:03 PM, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> On HSW/BDW with VT-d active the first tile row scanned out
> after the first async flip of the frame often ends up corrupted.
>
> Whether the corruption happens or not depends on the scanline
> on which the async flip happens, but the behaviour seems very
> consistent. Ie. the same set of scanlines (which are most scanlines)
> always show the corruption. And another set of scanlines (far less
> of them) never shows the corruption.
>
> I discovered that disabling the fetch-stride stretching
> feature cures the corruption. This is some kind of TLB related
> prefetch thing AFAIK. We already disable it on SNB primary
> planes due to a documented workaround. The hardware folks
> indicated that disabling this should be fine, so let's go
> with that.
>
> And while we're here, let's document the relevant bits on all
> pre-skl platforms.
>
> Fixes: 2a636e240c77 ("drm/i915: Implement async flip for ivb/hsw")
> Fixes: cda195f13abd ("drm/i915: Implement async flips for bdw")
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
Looks good to me.
Reviewed-by: Karthik B S <karthik.b.s at intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 23 ++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_pm.c | 16 +++++++++++++++-
> 2 files changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 224ad897af34..0bb0229a2e49 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3319,7 +3319,18 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>
> #define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000)
> #define ILK_FBCQ_DIS (1 << 22)
> -#define ILK_PABSTRETCH_DIS (1 << 21)
> +#define ILK_PABSTRETCH_DIS REG_BIT(21)
> +#define ILK_SABSTRETCH_DIS REG_BIT(20)
> +#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20)
> +#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0)
> +#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1)
> +#define IVB_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 2)
> +#define IVB_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 3)
> +#define IVB_SPR_STRETCH_MAX_MASK REG_GENMASK(19, 18)
> +#define IVB_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 0)
> +#define IVB_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 1)
> +#define IVB_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 2)
> +#define IVB_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 3)
>
>
> /*
> @@ -8042,6 +8053,16 @@ enum {
>
> #define _CHICKEN_PIPESL_1_A 0x420b0
> #define _CHICKEN_PIPESL_1_B 0x420b4
> +#define HSW_PRI_STRETCH_MAX_MASK REG_GENMASK(28, 27)
> +#define HSW_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 0)
> +#define HSW_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 1)
> +#define HSW_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 2)
> +#define HSW_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 3)
> +#define HSW_SPR_STRETCH_MAX_MASK REG_GENMASK(26, 25)
> +#define HSW_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 0)
> +#define HSW_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 1)
> +#define HSW_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 2)
> +#define HSW_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 3)
> #define HSW_FBCQ_DIS (1 << 22)
> #define BDW_DPRS_MASK_VBLANK_SRD (1 << 0)
> #define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 8cc67f9c4e58..53b04800f9d0 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -7243,11 +7243,16 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
> intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1,
> intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
>
> - /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
> for_each_pipe(dev_priv, pipe) {
> + /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
> intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
> intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe)) |
> BDW_DPRS_MASK_VBLANK_SRD);
> +
> + /* Undocumented but fixes async flip + VT-d corruption */
> + if (intel_vtd_active())
> + intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
> + HSW_PRI_STRETCH_MAX_MASK, HSW_PRI_STRETCH_MAX_X1);
> }
>
> /* WaVSRefCountFullforceMissDisable:bdw */
> @@ -7283,11 +7288,20 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
>
> static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
> {
> + enum pipe pipe;
> +
> /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
> intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A),
> intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A)) |
> HSW_FBCQ_DIS);
>
> + for_each_pipe(dev_priv, pipe) {
> + /* Undocumented but fixes async flip + VT-d corruption */
> + if (intel_vtd_active())
> + intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
> + HSW_PRI_STRETCH_MAX_MASK, HSW_PRI_STRETCH_MAX_X1);
> + }
> +
> /* This is required by WaCatErrorRejectionIssue:hsw */
> intel_uncore_write(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
> intel_uncore_read(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
More information about the Intel-gfx
mailing list