diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2017-09-14 18:17:31 +0300 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2017-09-25 16:54:09 +0300 |
commit | 6b12ca569bb2f864892c41dbbb0f88f3f9952bf3 (patch) | |
tree | 59b29795a209e6b84a0fcf4f3ae411c11e82f849 /drivers/gpu/drm/i915/intel_fifo_underrun.c | |
parent | dff457d74e7eaf8c5280967467597ebfc3e2e44a (diff) | |
download | linux-6b12ca569bb2f864892c41dbbb0f88f3f9952bf3.tar.xz |
drm/i915: Don't rmw PIPESTAT enable bits
i830 seems to occasionally forget the PIPESTAT enable bits when
we read the register. These aren't the only registers on i830 that
have problems with RMW, as reading the double buffered plane
registers returns the latched value rather than the last written
value. So something similar is perhaps going on with PIPESTAT.
This corruption results on vblank interrupts occasionally turning off
on their own, which leads to vblank timeouts and generally a stuck
display subsystem.
So let's not RMW the pipestat enable bits, and instead use the cached
copy we have around.
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170914151731.5034-1-ville.syrjala@linux.intel.com
Reviewed-by: Imre Deak <imre.deak@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fifo_underrun.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_fifo_underrun.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 04689600e337..77c123cc8817 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -88,14 +88,15 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); i915_reg_t reg = PIPESTAT(crtc->pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; + u32 enable_mask; lockdep_assert_held(&dev_priv->irq_lock); - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) + if ((I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0) return; - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe); + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe); @@ -108,15 +109,16 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, { struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; lockdep_assert_held(&dev_priv->irq_lock); if (enable) { - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); } else { - if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS) + if (old && I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); } } |