Hi, one comment below: On Fri, 2013-04-12 at 17:57 -0300, Paulo Zanoni wrote: > From: Paulo Zanoni <paulo.r.zanoni at intel.com> > > In this commit we enable both CPU and PCH FIFO underrun reporting and > start reporting them. We follow a few rules: > - after we receive one of these errors, we mask the interrupt, so > we won't get an "interrupt storm" and we also won't flood dmesg; > - at each mode set we enable the interrupts again, so we'll see each > message at most once per mode set; > - in the specific places where we need to ignore the errors, we > completely mask the interrupts. > > The downside of this patch is that since we're completely disabling > (masking) the interrupts instead of just not printing error messages, > we will mask more than just what we want on IVB/HSW CPU interrupts > (due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So > when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll > also be masking PCH FIFO underruns for pipe B, because both are > reported by SERR_INT, which has to be either completely enabled or > completely disabled (in othe words, there's no way to disable/enable > specific bits of GEN7_ERR_INT and SERR_INT). > > V2: Rename some functions and variables, downgrade messages to > DRM_DEBUG_DRIVER and rebase. > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com> > --- > drivers/gpu/drm/i915/i915_irq.c | 315 +++++++++++++++++++++++++++++++++- > drivers/gpu/drm/i915/i915_reg.h | 13 +- > drivers/gpu/drm/i915/intel_display.c | 14 ++ > drivers/gpu/drm/i915/intel_drv.h | 11 ++ > 4 files changed, 342 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index e97bbb2..9aff6ed 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -111,6 +111,213 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) > } > } > > +static bool ivb_can_enable_err_int(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_crtc *crtc; > + enum pipe pipe; > + > + for_each_pipe(pipe) { > + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); > + > + if (crtc->cpu_fifo_underrun_disabled) > + return false; > + } > + > + return true; > +} > + > +static bool cpt_can_enable_serr_int(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe; > + struct intel_crtc *crtc; > + > + for_each_pipe(pipe) { > + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); > + > + if (crtc->pch_fifo_underrun_disabled) > + return false; > + } > + > + return true; > +} > + > +static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev, > + enum pipe pipe, bool enable) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN : > + DE_PIPEB_FIFO_UNDERRUN; > + > + if (enable) > + ironlake_enable_display_irq(dev_priv, bit); > + else > + ironlake_disable_display_irq(dev_priv, bit); > +} > + > +static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, > + bool enable) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + if (enable) { > + if (!ivb_can_enable_err_int(dev)) > + return; > + > + I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN_A | > + ERR_INT_FIFO_UNDERRUN_B | > + ERR_INT_FIFO_UNDERRUN_C); > + > + ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); > + } else { > + ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); > + } > +} > + > +static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc, > + bool enable) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + uint32_t bit = (crtc->pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER : > + SDE_TRANSB_FIFO_UNDER; > + > + if (enable) > + I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~bit); > + else > + I915_WRITE(SDEIMR, I915_READ(SDEIMR) | bit); > + > + POSTING_READ(SDEIMR); > +} > + > +static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, > + enum transcoder pch_transcoder, > + bool enable) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + if (enable) { > + if (!cpt_can_enable_serr_int(dev)) > + return; > + > + I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN | > + SERR_INT_TRANS_B_FIFO_UNDERRUN | > + SERR_INT_TRANS_C_FIFO_UNDERRUN); We end up here for LPT too, but there only the TRANS_A bit is defined. Otherwise looks good: Reviewed-by: Imre Deak <imre.deak at intel.com> > + > + I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~SDE_ERROR_CPT); > + } else { > + I915_WRITE(SDEIMR, I915_READ(SDEIMR) | SDE_ERROR_CPT); > + } > + > + POSTING_READ(SDEIMR); > +} > + > +/** > + * intel_set_cpu_fifo_underrun_reporting - enable/disable FIFO underrun messages > + * @dev: drm device > + * @pipe: pipe > + * @enable: true if we want to report FIFO underrun errors, false otherwise > + * > + * This function makes us disable or enable CPU fifo underruns for a specific > + * pipe. Notice that on some Gens (e.g. IVB, HSW), disabling FIFO underrun > + * reporting for one pipe may also disable all the other CPU error interruts for > + * the other pipes, due to the fact that there's just one interrupt mask/enable > + * bit for all the pipes. > + * > + * Returns the previous state of underrun reporting. > + */ > +bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > + enum pipe pipe, bool enable) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + unsigned long flags; > + bool ret; > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + > + ret = !intel_crtc->cpu_fifo_underrun_disabled; > + > + if (enable == ret) > + goto done; > + > + intel_crtc->cpu_fifo_underrun_disabled = !enable; > + > + if (IS_GEN5(dev) || IS_GEN6(dev)) > + ironlake_set_fifo_underrun_reporting(dev, pipe, enable); > + else if (IS_GEN7(dev)) > + ivybridge_set_fifo_underrun_reporting(dev, enable); > + > +done: > + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); > + return ret; > +} > + > +/** > + * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages > + * @dev: drm device > + * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older) > + * @enable: true if we want to report FIFO underrun errors, false otherwise > + * > + * This function makes us disable or enable PCH fifo underruns for a specific > + * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO > + * underrun reporting for one transcoder may also disable all the other PCH > + * error interruts for the other transcoders, due to the fact that there's just > + * one interrupt mask/enable bit for all the transcoders. > + * > + * Returns the previous state of underrun reporting. > + */ > +bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, > + enum transcoder pch_transcoder, > + bool enable) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe p; > + struct drm_crtc *crtc; > + struct intel_crtc *intel_crtc; > + unsigned long flags; > + bool ret; > + > + if (HAS_PCH_LPT(dev)) { > + crtc = NULL; > + for_each_pipe(p) { > + struct drm_crtc *c = dev_priv->pipe_to_crtc_mapping[p]; > + if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) { > + crtc = c; > + break; > + } > + } > + if (!crtc) { > + DRM_ERROR("PCH FIFO underrun, but no CRTC using the PCH found\n"); > + return false; > + } > + } else { > + crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder]; > + } > + intel_crtc = to_intel_crtc(crtc); > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + > + ret = !intel_crtc->pch_fifo_underrun_disabled; > + > + if (enable == ret) > + goto done; > + > + intel_crtc->pch_fifo_underrun_disabled = !enable; > + > + if (HAS_PCH_IBX(dev)) > + ibx_set_fifo_underrun_reporting(intel_crtc, enable); > + else > + cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable); > + > +done: > + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); > + return ret; > +} > + > + > void > i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) > { > @@ -716,10 +923,58 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) > if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) > DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); > > - if (pch_iir & SDE_TRANSB_FIFO_UNDER) > - DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n"); > if (pch_iir & SDE_TRANSA_FIFO_UNDER) > - DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); > + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, > + false)) > + DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n"); > + > + if (pch_iir & SDE_TRANSB_FIFO_UNDER) > + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B, > + false)) > + DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n"); > +} > + > +static void ivb_err_int_handler(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 err_int = I915_READ(GEN7_ERR_INT); > + > + if (err_int & ERR_INT_FIFO_UNDERRUN_A) > + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) > + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); > + > + if (err_int & ERR_INT_FIFO_UNDERRUN_B) > + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) > + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); > + > + if (err_int & ERR_INT_FIFO_UNDERRUN_C) > + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false)) > + DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n"); > + > + I915_WRITE(GEN7_ERR_INT, err_int); > +} > + > +static void cpt_serr_int_handler(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + u32 serr_int = I915_READ(SERR_INT); > + > + if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN) > + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, > + false)) > + DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n"); > + > + if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN) > + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B, > + false)) > + DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n"); > + > + if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN) > + if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C, > + false)) > + DRM_DEBUG_DRIVER("PCH transcoder C FIFO underrun\n"); > + > + I915_WRITE(SERR_INT, serr_int); > } > > static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) > @@ -752,6 +1007,9 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) > DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", > pipe_name(pipe), > I915_READ(FDI_RX_IIR(pipe))); > + > + if (pch_iir & SDE_ERROR_CPT) > + cpt_serr_int_handler(dev); > } > > static irqreturn_t ivybridge_irq_handler(int irq, void *arg) > @@ -764,6 +1022,14 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) > > atomic_inc(&dev_priv->irq_received); > > + /* We get interrupts on unclaimed registers, so check for this before we > + * do any I915_{READ,WRITE}. */ > + if (IS_HASWELL(dev) && > + (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { > + DRM_ERROR("Unclaimed register before interrupt\n"); > + I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM); > + } > + > /* disable master interrupt before clearing iir */ > de_ier = I915_READ(DEIER); > I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); > @@ -779,6 +1045,12 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) > POSTING_READ(SDEIER); > } > > + /* On Haswell, also mask ERR_INT because we don't want to risk > + * generating "unclaimed register" interrupts from inside the interrupt > + * handler. */ > + if (IS_HASWELL(dev)) > + ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); > + > gt_iir = I915_READ(GTIIR); > if (gt_iir) { > snb_gt_irq_handler(dev, dev_priv, gt_iir); > @@ -788,6 +1060,9 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) > > de_iir = I915_READ(DEIIR); > if (de_iir) { > + if (de_iir & DE_ERR_INT_IVB) > + ivb_err_int_handler(dev); > + > if (de_iir & DE_AUX_CHANNEL_A_IVB) > dp_aux_irq_handler(dev); > > @@ -825,6 +1100,9 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) > ret = IRQ_HANDLED; > } > > + if (IS_HASWELL(dev) && ivb_can_enable_err_int(dev)) > + ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); > + > I915_WRITE(DEIER, de_ier); > POSTING_READ(DEIER); > if (!HAS_PCH_NOP(dev)) { > @@ -894,6 +1172,14 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) > if (de_iir & DE_PIPEB_VBLANK) > drm_handle_vblank(dev, 1); > > + if (de_iir & DE_PIPEA_FIFO_UNDERRUN) > + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) > + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); > + > + if (de_iir & DE_PIPEB_FIFO_UNDERRUN) > + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) > + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); > + > if (de_iir & DE_PLANEA_FLIP_DONE) { > intel_prepare_page_flip(dev, 0); > intel_finish_page_flip_plane(dev, 0); > @@ -2115,10 +2401,14 @@ static void ibx_irq_postinstall(struct drm_device *dev) > drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; > u32 mask; > > - if (HAS_PCH_IBX(dev)) > - mask = SDE_GMBUS | SDE_AUX_MASK; > - else > - mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; > + if (HAS_PCH_IBX(dev)) { > + mask = SDE_GMBUS | SDE_AUX_MASK | SDE_TRANSB_FIFO_UNDER | > + SDE_TRANSA_FIFO_UNDER; > + } else { > + mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT | SDE_ERROR_CPT; > + > + I915_WRITE(SERR_INT, I915_READ(SERR_INT)); > + } > > if (HAS_PCH_NOP(dev)) > return; > @@ -2133,7 +2423,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) > /* enable kind of interrupts always enabled */ > u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | > DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | > - DE_AUX_CHANNEL_A; > + DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN | > + DE_PIPEA_FIFO_UNDERRUN; > u32 render_irqs; > > dev_priv->irq_mask = ~display_mask; > @@ -2183,12 +2474,14 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) > DE_PLANEC_FLIP_DONE_IVB | > DE_PLANEB_FLIP_DONE_IVB | > DE_PLANEA_FLIP_DONE_IVB | > - DE_AUX_CHANNEL_A_IVB; > + DE_AUX_CHANNEL_A_IVB | > + DE_ERR_INT_IVB; > u32 render_irqs; > > dev_priv->irq_mask = ~display_mask; > > /* should always can generate irq */ > + I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT)); > I915_WRITE(DEIIR, I915_READ(DEIIR)); > I915_WRITE(DEIMR, dev_priv->irq_mask); > I915_WRITE(DEIER, > @@ -2312,6 +2605,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev) > I915_WRITE(DEIMR, 0xffffffff); > I915_WRITE(DEIER, 0x0); > I915_WRITE(DEIIR, I915_READ(DEIIR)); > + if (IS_GEN7(dev)) > + I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT)); > > I915_WRITE(GTIMR, 0xffffffff); > I915_WRITE(GTIER, 0x0); > @@ -2323,6 +2618,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev) > I915_WRITE(SDEIMR, 0xffffffff); > I915_WRITE(SDEIER, 0x0); > I915_WRITE(SDEIIR, I915_READ(SDEIIR)); > + if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev)) > + I915_WRITE(SERR_INT, I915_READ(SERR_INT)); > } > > static void i8xx_irq_preinstall(struct drm_device * dev) > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 76d9df1..932b4a0 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -529,7 +529,10 @@ > > #define ERROR_GEN6 0x040a0 > #define GEN7_ERR_INT 0x44040 > -#define ERR_INT_MMIO_UNCLAIMED (1<<13) > +#define ERR_INT_MMIO_UNCLAIMED (1<<13) > +#define ERR_INT_FIFO_UNDERRUN_C (1<<6) > +#define ERR_INT_FIFO_UNDERRUN_B (1<<3) > +#define ERR_INT_FIFO_UNDERRUN_A (1<<0) > > #define FPGA_DBG 0x42300 > #define FPGA_DBG_RM_NOCLAIM (1<<31) > @@ -3505,7 +3508,7 @@ > #define DE_PIPEA_FIFO_UNDERRUN (1 << 0) > > /* More Ivybridge lolz */ > -#define DE_ERR_DEBUG_IVB (1<<30) > +#define DE_ERR_INT_IVB (1<<30) > #define DE_GSE_IVB (1<<29) > #define DE_PCH_EVENT_IVB (1<<28) > #define DE_DP_A_HOTPLUG_IVB (1<<27) > @@ -3664,6 +3667,7 @@ > SDE_PORTC_HOTPLUG_CPT | \ > SDE_PORTB_HOTPLUG_CPT) > #define SDE_GMBUS_CPT (1 << 17) > +#define SDE_ERROR_CPT (1 << 16) > #define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) > #define SDE_AUDIO_CP_CHG_C_CPT (1 << 9) > #define SDE_FDI_RXC_CPT (1 << 8) > @@ -3688,6 +3692,11 @@ > #define SDEIIR 0xc4008 > #define SDEIER 0xc400c > > +#define SERR_INT 0xc4040 > +#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6) > +#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3) > +#define SERR_INT_TRANS_A_FIFO_UNDERRUN (1<<0) > + > /* digital port hotplug */ > #define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ > #define PORTD_HOTPLUG_ENABLE (1 << 20) > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 457a0a0..574d68d 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -3339,6 +3339,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) > return; > > intel_crtc->active = true; > + > + intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); > + intel_set_pch_fifo_underrun_reporting(dev, pipe, true); > + > intel_update_watermarks(dev); > > if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { > @@ -3430,6 +3434,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) > return; > > intel_crtc->active = true; > + > + intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); > + if (intel_crtc->config.has_pch_encoder) > + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); > + > intel_update_watermarks(dev); > > if (intel_crtc->config.has_pch_encoder) > @@ -3516,6 +3525,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) > if (dev_priv->cfb_plane == plane) > intel_disable_fbc(dev); > > + intel_set_pch_fifo_underrun_reporting(dev, pipe, false); > intel_disable_pipe(dev_priv, pipe); > > /* Disable PF */ > @@ -3529,6 +3539,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) > ironlake_fdi_disable(crtc); > > ironlake_disable_pch_transcoder(dev_priv, pipe); > + intel_set_pch_fifo_underrun_reporting(dev, pipe, true); > > if (HAS_PCH_CPT(dev)) { > /* disable TRANS_DP_CTL */ > @@ -3595,6 +3606,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) > if (dev_priv->cfb_plane == plane) > intel_disable_fbc(dev); > > + if (intel_crtc->config.has_pch_encoder) > + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false); > intel_disable_pipe(dev_priv, pipe); > > intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); > @@ -3611,6 +3624,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) > > if (intel_crtc->config.has_pch_encoder) { > lpt_disable_pch_transcoder(dev_priv); > + intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); > intel_ddi_fdi_disable(crtc); > } > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index d7bd031..fe3566c 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -258,6 +258,10 @@ struct intel_crtc { > > /* reset counter value when the last flip was submitted */ > unsigned int reset_counter; > + > + /* Access to these should be protected by dev_priv->irq_lock. */ > + bool cpu_fifo_underrun_disabled; > + bool pch_fifo_underrun_disabled; > }; > > struct intel_plane { > @@ -467,6 +471,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); > extern void intel_attach_force_audio_property(struct drm_connector *connector); > extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); > > +extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type); > extern void intel_crt_init(struct drm_device *dev); > extern void intel_hdmi_init(struct drm_device *dev, > int hdmi_reg, enum port port); > @@ -719,5 +724,11 @@ intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); > extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); > > extern void intel_display_handle_reset(struct drm_device *dev); > +extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > + enum pipe pipe, > + bool enable); > +extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, > + enum transcoder pch_transcoder, > + bool enable); > > #endif /* __INTEL_DRV_H__ */