Commit 2d9d2b0b authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Limit FIFO underrun reports on GMCH platforms

Currently we print all pipe underruns on GMCH platforms. Hook up the
same logic we use on PCH platforms where we disable the underrun
reporting after the first underrun.

Underruns don't actually generate interrupts themselves on GMCH
platforms, we just can detect them whenever we service other
interrupts. So we don't have any enable bits to worry about. We just
need to remember to clear the underrun status when enabling underrun
reporting.

Note that the underrun handling needs to be moved to the non-locked
pipe_stats[] loop in the interrupt handlers to avoid having to rework
the locking in intel_set_cpu_fifo_underrun_reporting().
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 20f0ec16
...@@ -232,6 +232,18 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) ...@@ -232,6 +232,18 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
return true; return true;
} }
static void i9xx_clear_fifo_underrun(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & 0x7fff0000;
assert_spin_locked(&dev_priv->irq_lock);
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
POSTING_READ(reg);
}
static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev, static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable) enum pipe pipe, bool enable)
{ {
...@@ -393,7 +405,9 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, ...@@ -393,7 +405,9 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
intel_crtc->cpu_fifo_underrun_disabled = !enable; intel_crtc->cpu_fifo_underrun_disabled = !enable;
if (IS_GEN5(dev) || IS_GEN6(dev)) if (enable && (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)))
i9xx_clear_fifo_underrun(dev, pipe);
else if (IS_GEN5(dev) || IS_GEN6(dev))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable); ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
else if (IS_GEN7(dev)) else if (IS_GEN7(dev))
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable); ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
...@@ -1454,12 +1468,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) ...@@ -1454,12 +1468,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
/* /*
* Clear the PIPE*STAT regs before the IIR * Clear the PIPE*STAT regs before the IIR
*/ */
if (pipe_stats[pipe] & 0x8000ffff) { if (pipe_stats[pipe] & 0x8000ffff)
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG_DRIVER("pipe %c underrun\n",
pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]); I915_WRITE(reg, pipe_stats[pipe]);
}
} }
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
...@@ -1474,6 +1484,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) ...@@ -1474,6 +1484,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
} }
/* Consume port. Then clear IIR or we'll miss events */ /* Consume port. Then clear IIR or we'll miss events */
...@@ -3198,12 +3212,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) ...@@ -3198,12 +3212,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
/* /*
* Clear the PIPE*STAT regs before the IIR * Clear the PIPE*STAT regs before the IIR
*/ */
if (pipe_stats[pipe] & 0x8000ffff) { if (pipe_stats[pipe] & 0x8000ffff)
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG_DRIVER("pipe %c underrun\n",
pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]); I915_WRITE(reg, pipe_stats[pipe]);
}
} }
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
...@@ -3226,6 +3236,10 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) ...@@ -3226,6 +3236,10 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
} }
iir = new_iir; iir = new_iir;
...@@ -3379,9 +3393,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) ...@@ -3379,9 +3393,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
/* Clear the PIPE*STAT regs before the IIR */ /* Clear the PIPE*STAT regs before the IIR */
if (pipe_stats[pipe] & 0x8000ffff) { if (pipe_stats[pipe] & 0x8000ffff) {
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG_DRIVER("pipe %c underrun\n",
pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]); I915_WRITE(reg, pipe_stats[pipe]);
irq_received = true; irq_received = true;
} }
...@@ -3423,6 +3434,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) ...@@ -3423,6 +3434,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
} }
if (blc_event || (iir & I915_ASLE_INTERRUPT)) if (blc_event || (iir & I915_ASLE_INTERRUPT))
...@@ -3617,9 +3632,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) ...@@ -3617,9 +3632,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
* Clear the PIPE*STAT regs before the IIR * Clear the PIPE*STAT regs before the IIR
*/ */
if (pipe_stats[pipe] & 0x8000ffff) { if (pipe_stats[pipe] & 0x8000ffff) {
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG_DRIVER("pipe %c underrun\n",
pipe_name(pipe));
I915_WRITE(reg, pipe_stats[pipe]); I915_WRITE(reg, pipe_stats[pipe]);
irq_received = true; irq_received = true;
} }
...@@ -3667,8 +3679,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) ...@@ -3667,8 +3679,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
}
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS &&
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
DRM_DEBUG_DRIVER("pipe %c underrun\n", pipe_name(pipe));
}
if (blc_event || (iir & I915_ASLE_INTERRUPT)) if (blc_event || (iir & I915_ASLE_INTERRUPT))
intel_opregion_asle_intr(dev); intel_opregion_asle_intr(dev);
......
...@@ -4170,6 +4170,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4170,6 +4170,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(crtc); intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe, false, is_dsi); intel_enable_pipe(dev_priv, pipe, false, is_dsi);
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_enable_primary_plane(dev_priv, plane, pipe); intel_enable_primary_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc); intel_enable_planes(crtc);
intel_crtc_update_cursor(crtc, true); intel_crtc_update_cursor(crtc, true);
...@@ -4208,6 +4209,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) ...@@ -4208,6 +4209,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(crtc); intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe, false, false); intel_enable_pipe(dev_priv, pipe, false, false);
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_enable_primary_plane(dev_priv, plane, pipe); intel_enable_primary_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc); intel_enable_planes(crtc);
/* The fixup needs to happen before cursor is enabled */ /* The fixup needs to happen before cursor is enabled */
...@@ -4266,6 +4268,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -4266,6 +4268,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_disable_planes(crtc); intel_disable_planes(crtc);
intel_disable_primary_plane(dev_priv, plane, pipe); intel_disable_primary_plane(dev_priv, plane, pipe);
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
intel_disable_pipe(dev_priv, pipe); intel_disable_pipe(dev_priv, pipe);
i9xx_pfit_disable(intel_crtc); i9xx_pfit_disable(intel_crtc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment