Message ID | 1446146763-31821-7-git-send-email-ville.syrjala@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Oct 29, 2015 at 09:25:55PM +0200, ville.syrjala@linux.intel.com wrote: > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > Due to the shared error interrupt on IVB/HSW and CPT/PPT we may not > always get an interrupt on a FIFO underrun. But we can always do an > explicit check (like we do on GMCH platforms that have no underrun > interrupt). > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/i915/intel_display.c | 6 +- > drivers/gpu/drm/i915/intel_drv.h | 3 +- > drivers/gpu/drm/i915/intel_fifo_underrun.c | 121 ++++++++++++++++++++++++----- > 3 files changed, 105 insertions(+), 25 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index c7cd9f7..e820147 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -4719,9 +4719,9 @@ intel_post_enable_primary(struct drm_crtc *crtc) > if (IS_GEN2(dev)) > intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); > > - /* Underruns don't raise interrupts, so check manually. */ > - if (HAS_GMCH_DISPLAY(dev)) > - i9xx_check_fifo_underruns(dev_priv); > + /* Underruns don't always raise interrupts, so check manually. */ > + intel_check_cpu_fifo_underruns(dev_priv); > + intel_check_pch_fifo_underruns(dev_priv); > } > > /** > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 1a3bbdc..72cc272 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -959,7 +959,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, > enum pipe pipe); > void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, > enum transcoder pch_transcoder); > -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv); > +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv); > +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); > > /* i915_irq.c */ > void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); > diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c > index 54daa66..a546fc3 100644 > --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c > +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c > @@ -85,37 +85,28 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) > } > > /** > - * i9xx_check_fifo_underruns - check for fifo underruns > - * @dev_priv: i915 device instance > + * intel_check_cpu_fifo_underruns - check for fifo underruns > + * @crtc: pipe > * > * This function checks for fifo underruns on GMCH platforms. This needs to be > * done manually on modeset to make sure that we catch all underruns since they > * do not generate an interrupt by themselves on these platforms. > */ Stale kerneldoc above, just delete it. With that fixed: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv) > +static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) > { > - struct intel_crtc *crtc; > - > - spin_lock_irq(&dev_priv->irq_lock); > - > - for_each_intel_crtc(dev_priv->dev, crtc) { > - u32 reg = PIPESTAT(crtc->pipe); > - u32 pipestat; > - > - if (crtc->cpu_fifo_underrun_disabled) > - continue; > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + u32 reg = PIPESTAT(crtc->pipe); > + u32 pipestat = I915_READ(reg) & 0xffff0000; > > - pipestat = I915_READ(reg) & 0xffff0000; > - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) > - continue; > + assert_spin_locked(&dev_priv->irq_lock); > > - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); > - POSTING_READ(reg); > + if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) > + return; > > - DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); > - } > + I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); > + POSTING_READ(reg); > > - spin_unlock_irq(&dev_priv->irq_lock); > + DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); > } > > static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, > @@ -150,6 +141,23 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev, > ironlake_disable_display_irq(dev_priv, bit); > } > > +static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + enum pipe pipe = crtc->pipe; > + uint32_t err_int = I915_READ(GEN7_ERR_INT); > + > + assert_spin_locked(&dev_priv->irq_lock); > + > + if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0) > + return; > + > + I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe)); > + POSTING_READ(GEN7_ERR_INT); > + > + DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe)); > +} > + > static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, > enum pipe pipe, > bool enable, bool old) > @@ -202,6 +210,24 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev, > ibx_disable_display_interrupt(dev_priv, bit); > } > > +static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + enum transcoder pch_transcoder = (enum transcoder) crtc->pipe; > + uint32_t serr_int = I915_READ(SERR_INT); > + > + assert_spin_locked(&dev_priv->irq_lock); > + > + if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0) > + return; > + > + I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); > + POSTING_READ(SERR_INT); > + > + DRM_ERROR("pch fifo underrun on pch transcoder %c\n", > + transcoder_name(pch_transcoder)); > +} > + > static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, > enum transcoder pch_transcoder, > bool enable, bool old) > @@ -375,3 +401,56 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, > DRM_ERROR("PCH transcoder %c FIFO underrun\n", > transcoder_name(pch_transcoder)); > } > + > +/** > + * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately > + * @dev_priv: i915 device instance > + * > + * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared > + * error interrupt may have been disabled, and so CPU fifo underruns won't > + * necessarily raise an interrupt, and on GMCH platforms where underruns never > + * raise an interrupt. > + */ > +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv) > +{ > + struct intel_crtc *crtc; > + > + spin_lock_irq(&dev_priv->irq_lock); > + > + for_each_intel_crtc(dev_priv->dev, crtc) { > + if (crtc->cpu_fifo_underrun_disabled) > + continue; > + > + if (HAS_GMCH_DISPLAY(dev_priv)) > + i9xx_check_fifo_underruns(crtc); > + else if (IS_GEN7(dev_priv)) > + ivybridge_check_fifo_underruns(crtc); > + } > + > + spin_unlock_irq(&dev_priv->irq_lock); > +} > + > +/** > + * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately > + * @dev_priv: i915 device instance > + * > + * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared > + * error interrupt may have been disabled, and so PCH fifo underruns won't > + * necessarily raise an interrupt. > + */ > +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv) > +{ > + struct intel_crtc *crtc; > + > + spin_lock_irq(&dev_priv->irq_lock); > + > + for_each_intel_crtc(dev_priv->dev, crtc) { > + if (crtc->pch_fifo_underrun_disabled) > + continue; > + > + if (HAS_PCH_CPT(dev_priv)) > + cpt_check_pch_fifo_underruns(crtc); > + } > + > + spin_unlock_irq(&dev_priv->irq_lock); > +} > -- > 2.4.10 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c7cd9f7..e820147 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4719,9 +4719,9 @@ intel_post_enable_primary(struct drm_crtc *crtc) if (IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - /* Underruns don't raise interrupts, so check manually. */ - if (HAS_GMCH_DISPLAY(dev)) - i9xx_check_fifo_underruns(dev_priv); + /* Underruns don't always raise interrupts, so check manually. */ + intel_check_cpu_fifo_underruns(dev_priv); + intel_check_pch_fifo_underruns(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1a3bbdc..72cc272 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -959,7 +959,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe); void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder); -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv); +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv); +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); /* i915_irq.c */ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 54daa66..a546fc3 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -85,37 +85,28 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) } /** - * i9xx_check_fifo_underruns - check for fifo underruns - * @dev_priv: i915 device instance + * intel_check_cpu_fifo_underruns - check for fifo underruns + * @crtc: pipe * * This function checks for fifo underruns on GMCH platforms. This needs to be * done manually on modeset to make sure that we catch all underruns since they * do not generate an interrupt by themselves on these platforms. */ -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv) +static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { - struct intel_crtc *crtc; - - spin_lock_irq(&dev_priv->irq_lock); - - for_each_intel_crtc(dev_priv->dev, crtc) { - u32 reg = PIPESTAT(crtc->pipe); - u32 pipestat; - - if (crtc->cpu_fifo_underrun_disabled) - continue; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 reg = PIPESTAT(crtc->pipe); + u32 pipestat = I915_READ(reg) & 0xffff0000; - pipestat = I915_READ(reg) & 0xffff0000; - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) - continue; + assert_spin_locked(&dev_priv->irq_lock); - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); - POSTING_READ(reg); + if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) + return; - DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); - } + I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + POSTING_READ(reg); - spin_unlock_irq(&dev_priv->irq_lock); + DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); } static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, @@ -150,6 +141,23 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev, ironlake_disable_display_irq(dev_priv, bit); } +static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + uint32_t err_int = I915_READ(GEN7_ERR_INT); + + assert_spin_locked(&dev_priv->irq_lock); + + if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0) + return; + + I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe)); + POSTING_READ(GEN7_ERR_INT); + + DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe)); +} + static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, enum pipe pipe, bool enable, bool old) @@ -202,6 +210,24 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev, ibx_disable_display_interrupt(dev_priv, bit); } +static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder pch_transcoder = (enum transcoder) crtc->pipe; + uint32_t serr_int = I915_READ(SERR_INT); + + assert_spin_locked(&dev_priv->irq_lock); + + if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0) + return; + + I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); + POSTING_READ(SERR_INT); + + DRM_ERROR("pch fifo underrun on pch transcoder %c\n", + transcoder_name(pch_transcoder)); +} + static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, enum transcoder pch_transcoder, bool enable, bool old) @@ -375,3 +401,56 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, DRM_ERROR("PCH transcoder %c FIFO underrun\n", transcoder_name(pch_transcoder)); } + +/** + * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately + * @dev_priv: i915 device instance + * + * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared + * error interrupt may have been disabled, and so CPU fifo underruns won't + * necessarily raise an interrupt, and on GMCH platforms where underruns never + * raise an interrupt. + */ +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; + + spin_lock_irq(&dev_priv->irq_lock); + + for_each_intel_crtc(dev_priv->dev, crtc) { + if (crtc->cpu_fifo_underrun_disabled) + continue; + + if (HAS_GMCH_DISPLAY(dev_priv)) + i9xx_check_fifo_underruns(crtc); + else if (IS_GEN7(dev_priv)) + ivybridge_check_fifo_underruns(crtc); + } + + spin_unlock_irq(&dev_priv->irq_lock); +} + +/** + * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately + * @dev_priv: i915 device instance + * + * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared + * error interrupt may have been disabled, and so PCH fifo underruns won't + * necessarily raise an interrupt. + */ +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; + + spin_lock_irq(&dev_priv->irq_lock); + + for_each_intel_crtc(dev_priv->dev, crtc) { + if (crtc->pch_fifo_underrun_disabled) + continue; + + if (HAS_PCH_CPT(dev_priv)) + cpt_check_pch_fifo_underruns(crtc); + } + + spin_unlock_irq(&dev_priv->irq_lock); +}