From: Ville Syrjälä <ville.syrj...@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.syrj...@linux.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) |
-- 
2.26.2

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

Reply via email to