drm/i915: WARN if we receive any rps interrupts on gen>9
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_irq.c
index f17bbf3ac136994464bc5881729d4db27a485c2c..21c579e74451074007060ffe3582738e138c8498 100644 (file)
@@ -126,20 +126,22 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
 
 #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
        GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
-       I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
        I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
-       POSTING_READ(GEN8_##type##_IER(which)); \
+       I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
+       POSTING_READ(GEN8_##type##_IMR(which)); \
 } while (0)
 
 #define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
        GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
-       I915_WRITE(type##IMR, (imr_val)); \
        I915_WRITE(type##IER, (ier_val)); \
-       POSTING_READ(type##IER); \
+       I915_WRITE(type##IMR, (imr_val)); \
+       POSTING_READ(type##IMR); \
 } while (0)
 
+static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
+
 /* For display hotplug interrupt */
-static void
+void
 ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        assert_spin_locked(&dev_priv->irq_lock);
@@ -154,7 +156,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
        }
 }
 
-static void
+void
 ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        assert_spin_locked(&dev_priv->irq_lock);
@@ -200,71 +202,28 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
        ilk_update_gt_irq(dev_priv, mask, 0);
 }
 
-/**
-  * snb_update_pm_irq - update GEN6_PMIMR
-  * @dev_priv: driver private
-  * @interrupt_mask: mask of interrupt bits to update
-  * @enabled_irq_mask: mask of interrupt bits to enable
-  */
-static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
-                             uint32_t interrupt_mask,
-                             uint32_t enabled_irq_mask)
-{
-       uint32_t new_val;
-
-       assert_spin_locked(&dev_priv->irq_lock);
-
-       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
-               return;
-
-       new_val = dev_priv->pm_irq_mask;
-       new_val &= ~interrupt_mask;
-       new_val |= (~enabled_irq_mask & interrupt_mask);
-
-       if (new_val != dev_priv->pm_irq_mask) {
-               dev_priv->pm_irq_mask = new_val;
-               I915_WRITE(GEN6_PMIMR, dev_priv->pm_irq_mask);
-               POSTING_READ(GEN6_PMIMR);
-       }
-}
-
-void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+static u32 gen6_pm_iir(struct drm_i915_private *dev_priv)
 {
-       snb_update_pm_irq(dev_priv, mask, mask);
+       return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR;
 }
 
-void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+static u32 gen6_pm_imr(struct drm_i915_private *dev_priv)
 {
-       snb_update_pm_irq(dev_priv, mask, 0);
+       return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IMR(2) : GEN6_PMIMR;
 }
 
-static bool ivb_can_enable_err_int(struct drm_device *dev)
+static u32 gen6_pm_ier(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *crtc;
-       enum pipe pipe;
-
-       assert_spin_locked(&dev_priv->irq_lock);
-
-       for_each_pipe(dev_priv, pipe) {
-               crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-
-               if (crtc->cpu_fifo_underrun_disabled)
-                       return false;
-       }
-
-       return true;
+       return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IER(2) : GEN6_PMIER;
 }
 
 /**
-  * bdw_update_pm_irq - update GT interrupt 2
+  * snb_update_pm_irq - update GEN6_PMIMR
   * @dev_priv: driver private
   * @interrupt_mask: mask of interrupt bits to update
   * @enabled_irq_mask: mask of interrupt bits to enable
-  *
-  * Copied from the snb function, updated with relevant register offsets
   */
-static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
+static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
                              uint32_t interrupt_mask,
                              uint32_t enabled_irq_mask)
 {
@@ -281,134 +240,50 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
 
        if (new_val != dev_priv->pm_irq_mask) {
                dev_priv->pm_irq_mask = new_val;
-               I915_WRITE(GEN8_GT_IMR(2), dev_priv->pm_irq_mask);
-               POSTING_READ(GEN8_GT_IMR(2));
+               I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_irq_mask);
+               POSTING_READ(gen6_pm_imr(dev_priv));
        }
 }
 
-void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
-{
-       bdw_update_pm_irq(dev_priv, mask, mask);
-}
-
-void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
-       bdw_update_pm_irq(dev_priv, mask, 0);
+       snb_update_pm_irq(dev_priv, mask, mask);
 }
 
-static bool cpt_can_enable_serr_int(struct drm_device *dev)
+void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       enum pipe pipe;
-       struct intel_crtc *crtc;
-
-       assert_spin_locked(&dev_priv->irq_lock);
-
-       for_each_pipe(dev_priv, pipe) {
-               crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-
-               if (crtc->pch_fifo_underrun_disabled)
-                       return false;
-       }
-
-       return true;
+       snb_update_pm_irq(dev_priv, mask, 0);
 }
 
-void i9xx_check_fifo_underruns(struct drm_device *dev)
+void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *crtc;
 
        spin_lock_irq(&dev_priv->irq_lock);
-
-       for_each_intel_crtc(dev, crtc) {
-               u32 reg = PIPESTAT(crtc->pipe);
-               u32 pipestat;
-
-               if (crtc->cpu_fifo_underrun_disabled)
-                       continue;
-
-               pipestat = I915_READ(reg) & 0xffff0000;
-               if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
-                       continue;
-
-               I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
-               POSTING_READ(reg);
-
-               DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
-       }
-
+       WARN_ON(dev_priv->rps.pm_iir);
+       gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+       I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);
        spin_unlock_irq(&dev_priv->irq_lock);
 }
 
-static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
-                                            enum pipe pipe,
-                                            bool enable, bool old)
+void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg = PIPESTAT(pipe);
-       u32 pipestat = I915_READ(reg) & 0xffff0000;
-
-       assert_spin_locked(&dev_priv->irq_lock);
-
-       if (enable) {
-               I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
-               POSTING_READ(reg);
-       } else {
-               if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
-                       DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
-       }
-}
-
-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,
-                                                 enum pipe pipe,
-                                                 bool enable, bool old)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       if (enable) {
-               I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
-
-               if (!ivb_can_enable_err_int(dev))
-                       return;
-
-               ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
-       } else {
-               ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
 
-               if (old &&
-                   I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
-                       DRM_ERROR("uncleared fifo underrun on pipe %c\n",
-                                 pipe_name(pipe));
-               }
-       }
-}
-
-static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
-                                                 enum pipe pipe, bool enable)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ?
+                  ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0);
+       I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) &
+                               ~dev_priv->pm_rps_events);
+       /* Complete PM interrupt masking here doesn't race with the rps work
+        * item again unmasking PM interrupts because that is using a different
+        * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+        * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       spin_lock_irq(&dev_priv->irq_lock);
+       dev_priv->rps.pm_iir = 0;
+       spin_unlock_irq(&dev_priv->irq_lock);
 
-       if (enable)
-               dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
-       else
-               dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
-       I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
-       POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+       I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);
 }
 
 /**
@@ -417,9 +292,9 @@ static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
  * @interrupt_mask: mask of interrupt bits to update
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
-static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
-                                        uint32_t interrupt_mask,
-                                        uint32_t enabled_irq_mask)
+void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
+                                 uint32_t interrupt_mask,
+                                 uint32_t enabled_irq_mask)
 {
        uint32_t sdeimr = I915_READ(SDEIMR);
        sdeimr &= ~interrupt_mask;
@@ -433,160 +308,6 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
        I915_WRITE(SDEIMR, sdeimr);
        POSTING_READ(SDEIMR);
 }
-#define ibx_enable_display_interrupt(dev_priv, bits) \
-       ibx_display_interrupt_update((dev_priv), (bits), (bits))
-#define ibx_disable_display_interrupt(dev_priv, bits) \
-       ibx_display_interrupt_update((dev_priv), (bits), 0)
-
-static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
-                                           enum transcoder pch_transcoder,
-                                           bool enable)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
-                      SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
-
-       if (enable)
-               ibx_enable_display_interrupt(dev_priv, bit);
-       else
-               ibx_disable_display_interrupt(dev_priv, bit);
-}
-
-static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
-                                           enum transcoder pch_transcoder,
-                                           bool enable, bool old)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (enable) {
-               I915_WRITE(SERR_INT,
-                          SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
-
-               if (!cpt_can_enable_serr_int(dev))
-                       return;
-
-               ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
-       } else {
-               ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
-
-               if (old && I915_READ(SERR_INT) &
-                   SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
-                       DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
-                                 transcoder_name(pch_transcoder));
-               }
-       }
-}
-
-/**
- * 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.
- */
-static 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);
-       bool old;
-
-       assert_spin_locked(&dev_priv->irq_lock);
-
-       old = !intel_crtc->cpu_fifo_underrun_disabled;
-       intel_crtc->cpu_fifo_underrun_disabled = !enable;
-
-       if (HAS_GMCH_DISPLAY(dev))
-               i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
-       else 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, pipe, enable, old);
-       else if (IS_GEN8(dev) || IS_GEN9(dev))
-               broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
-
-       return old;
-}
-
-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;
-       unsigned long flags;
-       bool ret;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       ret = __intel_set_cpu_fifo_underrun_reporting(dev, pipe, enable);
-       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
-
-       return ret;
-}
-
-static bool __cpu_fifo_underrun_reporting_enabled(struct drm_device *dev,
-                                                 enum pipe pipe)
-{
-       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);
-
-       return !intel_crtc->cpu_fifo_underrun_disabled;
-}
-
-/**
- * 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;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       unsigned long flags;
-       bool old;
-
-       /*
-        * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
-        * has only one pch transcoder A that all pipes can use. To avoid racy
-        * pch transcoder -> pipe lookups from interrupt code simply store the
-        * underrun statistics in crtc A. Since we never expose this anywhere
-        * nor use it outside of the fifo underrun code here using the "wrong"
-        * crtc on LPT won't cause issues.
-        */
-
-       spin_lock_irqsave(&dev_priv->irq_lock, flags);
-
-       old = !intel_crtc->pch_fifo_underrun_disabled;
-       intel_crtc->pch_fifo_underrun_disabled = !enable;
-
-       if (HAS_PCH_IBX(dev))
-               ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
-       else
-               cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable, old);
-
-       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
-       return old;
-}
-
 
 static void
 __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
@@ -1266,11 +987,7 @@ static void notify_ring(struct drm_device *dev,
 
        trace_i915_gem_request_complete(ring);
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               intel_notify_mmio_flip(ring);
-
        wake_up_all(&ring->irq_queue);
-       i915_queue_hangcheck(dev);
 }
 
 static u32 vlv_c0_residency(struct drm_i915_private *dev_priv,
@@ -1408,12 +1125,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
        spin_lock_irq(&dev_priv->irq_lock);
        pm_iir = dev_priv->rps.pm_iir;
        dev_priv->rps.pm_iir = 0;
-       if (INTEL_INFO(dev_priv->dev)->gen >= 8)
-               gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
-       else {
-               /* Make sure not to corrupt PMIMR state used by ringbuffer */
-               gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
-       }
+       /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
+       gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
        spin_unlock_irq(&dev_priv->irq_lock);
 
        /* Make sure we didn't queue anything we're not going to process. */
@@ -1615,19 +1328,6 @@ static void snb_gt_irq_handler(struct drm_device *dev,
                ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
-static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
-{
-       if ((pm_iir & dev_priv->pm_rps_events) == 0)
-               return;
-
-       spin_lock(&dev_priv->irq_lock);
-       dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
-       gen8_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
-       spin_unlock(&dev_priv->irq_lock);
-
-       queue_work(dev_priv->wq, &dev_priv->rps.work);
-}
-
 static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
                                       struct drm_i915_private *dev_priv,
                                       u32 master_ctl)
@@ -1689,7 +1389,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
                        I915_WRITE(GEN8_GT_IIR(2),
                                   tmp & dev_priv->pm_rps_events);
                        ret = IRQ_HANDLED;
-                       gen8_rps_irq_handler(dev_priv, tmp);
+                       gen6_rps_irq_handler(dev_priv, tmp);
                } else
                        DRM_ERROR("The master control interrupt lied (PM)!\n");
        }
@@ -1989,6 +1689,11 @@ static void i9xx_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe)
  * the work queue. */
 static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
 {
+       /* TODO: RPS on GEN9+ is not supported yet. */
+       if (WARN_ONCE(INTEL_INFO(dev_priv)->gen >= 9,
+                     "GEN9+: unexpected RPS IRQ\n"))
+               return;
+
        if (pm_iir & dev_priv->pm_rps_events) {
                spin_lock(&dev_priv->irq_lock);
                dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
@@ -1998,6 +1703,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
                queue_work(dev_priv->wq, &dev_priv->rps.work);
        }
 
+       if (INTEL_INFO(dev_priv)->gen >= 8)
+               return;
+
        if (HAS_VEBOX(dev_priv->dev)) {
                if (pm_iir & PM_VEBOX_USER_INTERRUPT)
                        notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
@@ -2036,9 +1744,9 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
                 * we need to be careful that we only handle what we want to
                 * handle.
                 */
-               mask = 0;
-               if (__cpu_fifo_underrun_reporting_enabled(dev, pipe))
-                       mask |= PIPE_FIFO_UNDERRUN_STATUS;
+
+               /* fifo underruns are filterered in the underrun handler. */
+               mask = PIPE_FIFO_UNDERRUN_STATUS;
 
                switch (pipe) {
                case PIPE_A:
@@ -2083,9 +1791,8 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
                if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                        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_ERROR("pipe %c underrun\n", pipe_name(pipe));
+               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                       intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
        }
 
        if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
@@ -2252,14 +1959,10 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
                DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
 
        if (pch_iir & SDE_TRANSA_FIFO_UNDER)
-               if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
-                                                         false))
-                       DRM_ERROR("PCH transcoder A FIFO underrun\n");
+               intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_A);
 
        if (pch_iir & SDE_TRANSB_FIFO_UNDER)
-               if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
-                                                         false))
-                       DRM_ERROR("PCH transcoder B FIFO underrun\n");
+               intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_B);
 }
 
 static void ivb_err_int_handler(struct drm_device *dev)
@@ -2272,12 +1975,8 @@ static void ivb_err_int_handler(struct drm_device *dev)
                DRM_ERROR("Poison interrupt\n");
 
        for_each_pipe(dev_priv, pipe) {
-               if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) {
-                       if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
-                                                                 false))
-                               DRM_ERROR("Pipe %c FIFO underrun\n",
-                                         pipe_name(pipe));
-               }
+               if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
+                       intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
 
                if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
                        if (IS_IVYBRIDGE(dev))
@@ -2299,19 +1998,13 @@ static void cpt_serr_int_handler(struct drm_device *dev)
                DRM_ERROR("PCH poison interrupt\n");
 
        if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN)
-               if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
-                                                         false))
-                       DRM_ERROR("PCH transcoder A FIFO underrun\n");
+               intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_A);
 
        if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN)
-               if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
-                                                         false))
-                       DRM_ERROR("PCH transcoder B FIFO underrun\n");
+               intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_B);
 
        if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN)
-               if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C,
-                                                         false))
-                       DRM_ERROR("PCH transcoder C FIFO underrun\n");
+               intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_C);
 
        I915_WRITE(SERR_INT, serr_int);
 }
@@ -2377,9 +2070,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
                        intel_check_page_flip(dev, pipe);
 
                if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
-                       if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
-                               DRM_ERROR("Pipe %c FIFO underrun\n",
-                                         pipe_name(pipe));
+                       intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
 
                if (de_iir & DE_PIPE_CRC_DONE(pipe))
                        i9xx_pipe_crc_irq_handler(dev, pipe);
@@ -2529,6 +2220,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        irqreturn_t ret = IRQ_NONE;
        uint32_t tmp = 0;
        enum pipe pipe;
+       u32 aux_mask = GEN8_AUX_CHANNEL_A;
+
+       if (IS_GEN9(dev))
+               aux_mask |=  GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
+                       GEN9_AUX_CHANNEL_D;
 
        master_ctl = I915_READ(GEN8_MASTER_IRQ);
        master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
@@ -2561,7 +2257,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                if (tmp) {
                        I915_WRITE(GEN8_DE_PORT_IIR, tmp);
                        ret = IRQ_HANDLED;
-                       if (tmp & GEN8_AUX_CHANNEL_A)
+
+                       if (tmp & aux_mask)
                                dp_aux_irq_handler(dev);
                        else
                                DRM_ERROR("Unexpected DE Port interrupt\n");
@@ -2598,12 +2295,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                        if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
                                hsw_pipe_crc_irq_handler(dev, pipe);
 
-                       if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
-                               if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
-                                                                         false))
-                                       DRM_ERROR("Pipe %c FIFO underrun\n",
-                                                 pipe_name(pipe));
-                       }
+                       if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN)
+                               intel_cpu_fifo_underrun_irq_handler(dev_priv,
+                                                                   pipe);
 
 
                        if (IS_GEN9(dev))
@@ -3346,11 +3040,15 @@ static void i915_hangcheck_elapsed(unsigned long data)
 void i915_queue_hangcheck(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct timer_list *timer = &dev_priv->gpu_error.hangcheck_timer;
+
        if (!i915.enable_hangcheck)
                return;
 
-       mod_timer(&dev_priv->gpu_error.hangcheck_timer,
-                 round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
+       /* Don't continually defer the hangcheck, but make sure it is active */
+       if (!timer_pending(timer))
+               timer->expires = round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES);
+       mod_timer(timer, timer->expires);
 }
 
 static void ibx_irq_reset(struct drm_device *dev)
@@ -3412,10 +3110,22 @@ static void ironlake_irq_reset(struct drm_device *dev)
        ibx_irq_reset(dev);
 }
 
+static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
+{
+       enum pipe pipe;
+
+       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+
+       for_each_pipe(dev_priv, pipe)
+               I915_WRITE(PIPESTAT(pipe), 0xffff);
+
+       GEN5_IRQ_RESET(VLV_);
+}
+
 static void valleyview_irq_preinstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
 
        /* VLV magic */
        I915_WRITE(VLV_IMR, 0);
@@ -3423,22 +3133,11 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
        I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
        I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
 
-       /* and GT */
-       I915_WRITE(GTIIR, I915_READ(GTIIR));
-       I915_WRITE(GTIIR, I915_READ(GTIIR));
-
        gen5_gt_irq_reset(dev);
 
-       I915_WRITE(DPINVGTT, 0xff);
+       I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
-       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-       for_each_pipe(dev_priv, pipe)
-               I915_WRITE(PIPESTAT(pipe), 0xffff);
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       I915_WRITE(VLV_IMR, 0xffffffff);
-       I915_WRITE(VLV_IER, 0x0);
-       POSTING_READ(VLV_IER);
+       vlv_display_irq_reset(dev_priv);
 }
 
 static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv)
@@ -3486,7 +3185,6 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv)
 static void cherryview_irq_preinstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
 
        I915_WRITE(GEN8_MASTER_IRQ, 0);
        POSTING_READ(GEN8_MASTER_IRQ);
@@ -3495,20 +3193,9 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
 
        GEN5_IRQ_RESET(GEN8_PCU_);
 
-       POSTING_READ(GEN8_PCU_IIR);
-
        I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
-       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-
-       for_each_pipe(dev_priv, pipe)
-               I915_WRITE(PIPESTAT(pipe), 0xffff);
-
-       I915_WRITE(VLV_IMR, 0xffffffff);
-       I915_WRITE(VLV_IER, 0x0);
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       POSTING_READ(VLV_IIR);
+       vlv_display_irq_reset(dev_priv);
 }
 
 static void ibx_hpd_irq_setup(struct drm_device *dev)
@@ -3649,45 +3336,51 @@ static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
 {
        u32 pipestat_mask;
        u32 iir_mask;
+       enum pipe pipe;
 
        pipestat_mask = PIPESTAT_INT_STATUS_MASK |
                        PIPE_FIFO_UNDERRUN_STATUS;
 
-       I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
-       I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
+       for_each_pipe(dev_priv, pipe)
+               I915_WRITE(PIPESTAT(pipe), pipestat_mask);
        POSTING_READ(PIPESTAT(PIPE_A));
 
        pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
                        PIPE_CRC_DONE_INTERRUPT_STATUS;
 
-       i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
-                                              PIPE_GMBUS_INTERRUPT_STATUS);
-       i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+       for_each_pipe(dev_priv, pipe)
+                     i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
 
        iir_mask = I915_DISPLAY_PORT_INTERRUPT |
                   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
                   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+       if (IS_CHERRYVIEW(dev_priv))
+               iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
        dev_priv->irq_mask &= ~iir_mask;
 
        I915_WRITE(VLV_IIR, iir_mask);
        I915_WRITE(VLV_IIR, iir_mask);
-       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
        I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
-       POSTING_READ(VLV_IER);
+       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+       POSTING_READ(VLV_IMR);
 }
 
 static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
 {
        u32 pipestat_mask;
        u32 iir_mask;
+       enum pipe pipe;
 
        iir_mask = I915_DISPLAY_PORT_INTERRUPT |
                   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
                   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+       if (IS_CHERRYVIEW(dev_priv))
+               iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
 
        dev_priv->irq_mask |= iir_mask;
-       I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
        I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+       I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
        I915_WRITE(VLV_IIR, iir_mask);
        I915_WRITE(VLV_IIR, iir_mask);
        POSTING_READ(VLV_IIR);
@@ -3695,14 +3388,15 @@ static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
        pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
                        PIPE_CRC_DONE_INTERRUPT_STATUS;
 
-       i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
-                                               PIPE_GMBUS_INTERRUPT_STATUS);
-       i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
+       i915_disable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+       for_each_pipe(dev_priv, pipe)
+               i915_disable_pipestat(dev_priv, pipe, pipestat_mask);
 
        pipestat_mask = PIPESTAT_INT_STATUS_MASK |
                        PIPE_FIFO_UNDERRUN_STATUS;
-       I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
-       I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
+
+       for_each_pipe(dev_priv, pipe)
+               I915_WRITE(PIPESTAT(pipe), pipestat_mask);
        POSTING_READ(PIPESTAT(PIPE_A));
 }
 
@@ -3732,19 +3426,18 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
                valleyview_display_irqs_uninstall(dev_priv);
 }
 
-static int valleyview_irq_postinstall(struct drm_device *dev)
+static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
        dev_priv->irq_mask = ~0;
 
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        POSTING_READ(PORT_HOTPLUG_EN);
 
-       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-       I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
        I915_WRITE(VLV_IIR, 0xffffffff);
-       POSTING_READ(VLV_IER);
+       I915_WRITE(VLV_IIR, 0xffffffff);
+       I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
+       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+       POSTING_READ(VLV_IMR);
 
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
@@ -3752,9 +3445,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
        if (dev_priv->display_irqs_enabled)
                valleyview_display_irqs_install(dev_priv);
        spin_unlock_irq(&dev_priv->irq_lock);
+}
 
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       I915_WRITE(VLV_IIR, 0xffffffff);
+static int valleyview_irq_postinstall(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       vlv_display_irq_postinstall(dev_priv);
 
        gen5_gt_irq_postinstall(dev);
 
@@ -3799,11 +3496,14 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
        uint32_t de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE;
        uint32_t de_pipe_enables;
        int pipe;
+       u32 aux_en = GEN8_AUX_CHANNEL_A;
 
-       if (IS_GEN9(dev_priv))
+       if (IS_GEN9(dev_priv)) {
                de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE |
                                  GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
-       else
+               aux_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
+                       GEN9_AUX_CHANNEL_D;
+       } else
                de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE |
                                  GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
 
@@ -3821,7 +3521,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
                                          dev_priv->de_irq_mask[pipe],
                                          de_pipe_enables);
 
-       GEN5_IRQ_INIT(GEN8_DE_PORT_, ~GEN8_AUX_CHANNEL_A, GEN8_AUX_CHANNEL_A);
+       GEN5_IRQ_INIT(GEN8_DE_PORT_, ~aux_en, aux_en);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
@@ -3844,32 +3544,8 @@ static int gen8_irq_postinstall(struct drm_device *dev)
 static int cherryview_irq_postinstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 enable_mask = I915_DISPLAY_PORT_INTERRUPT |
-               I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
-               I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
-       u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
-               PIPE_CRC_DONE_INTERRUPT_STATUS;
-       int pipe;
-
-       /*
-        * Leave vblank interrupts masked initially.  enable/disable will
-        * toggle them based on usage.
-        */
-       dev_priv->irq_mask = ~enable_mask;
-
-       for_each_pipe(dev_priv, pipe)
-               I915_WRITE(PIPESTAT(pipe), 0xffff);
-
-       spin_lock_irq(&dev_priv->irq_lock);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
-       for_each_pipe(dev_priv, pipe)
-               i915_enable_pipestat(dev_priv, pipe, pipestat_enable);
-       spin_unlock_irq(&dev_priv->irq_lock);
 
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-       I915_WRITE(VLV_IER, enable_mask);
+       vlv_display_irq_postinstall(dev_priv);
 
        gen8_gt_irq_postinstall(dev_priv);
 
@@ -3889,42 +3565,39 @@ static void gen8_irq_uninstall(struct drm_device *dev)
        gen8_irq_reset(dev);
 }
 
+static void vlv_display_irq_uninstall(struct drm_i915_private *dev_priv)
+{
+       /* Interrupt setup is already guaranteed to be single-threaded, this is
+        * just to make the assert_spin_locked check happy. */
+       spin_lock_irq(&dev_priv->irq_lock);
+       if (dev_priv->display_irqs_enabled)
+               valleyview_display_irqs_uninstall(dev_priv);
+       spin_unlock_irq(&dev_priv->irq_lock);
+
+       vlv_display_irq_reset(dev_priv);
+
+       dev_priv->irq_mask = 0;
+}
+
 static void valleyview_irq_uninstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
 
        if (!dev_priv)
                return;
 
        I915_WRITE(VLV_MASTER_IER, 0);
 
-       for_each_pipe(dev_priv, pipe)
-               I915_WRITE(PIPESTAT(pipe), 0xffff);
+       gen5_gt_irq_reset(dev);
 
        I915_WRITE(HWSTAM, 0xffffffff);
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
-       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-
-       /* Interrupt setup is already guaranteed to be single-threaded, this is
-        * just to make the assert_spin_locked check happy. */
-       spin_lock_irq(&dev_priv->irq_lock);
-       if (dev_priv->display_irqs_enabled)
-               valleyview_display_irqs_uninstall(dev_priv);
-       spin_unlock_irq(&dev_priv->irq_lock);
 
-       dev_priv->irq_mask = 0;
-
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       I915_WRITE(VLV_IMR, 0xffffffff);
-       I915_WRITE(VLV_IER, 0x0);
-       POSTING_READ(VLV_IER);
+       vlv_display_irq_uninstall(dev_priv);
 }
 
 static void cherryview_irq_uninstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
 
        if (!dev_priv)
                return;
@@ -3932,44 +3605,11 @@ static void cherryview_irq_uninstall(struct drm_device *dev)
        I915_WRITE(GEN8_MASTER_IRQ, 0);
        POSTING_READ(GEN8_MASTER_IRQ);
 
-#define GEN8_IRQ_FINI_NDX(type, which)                         \
-do {                                                           \
-       I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff);       \
-       I915_WRITE(GEN8_##type##_IER(which), 0);                \
-       I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff);       \
-       POSTING_READ(GEN8_##type##_IIR(which));                 \
-       I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff);       \
-} while (0)
-
-#define GEN8_IRQ_FINI(type)                            \
-do {                                                   \
-       I915_WRITE(GEN8_##type##_IMR, 0xffffffff);      \
-       I915_WRITE(GEN8_##type##_IER, 0);               \
-       I915_WRITE(GEN8_##type##_IIR, 0xffffffff);      \
-       POSTING_READ(GEN8_##type##_IIR);                \
-       I915_WRITE(GEN8_##type##_IIR, 0xffffffff);      \
-} while (0)
-
-       GEN8_IRQ_FINI_NDX(GT, 0);
-       GEN8_IRQ_FINI_NDX(GT, 1);
-       GEN8_IRQ_FINI_NDX(GT, 2);
-       GEN8_IRQ_FINI_NDX(GT, 3);
-
-       GEN8_IRQ_FINI(PCU);
-
-#undef GEN8_IRQ_FINI
-#undef GEN8_IRQ_FINI_NDX
-
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
-       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       gen8_gt_irq_reset(dev_priv);
 
-       for_each_pipe(dev_priv, pipe)
-               I915_WRITE(PIPESTAT(pipe), 0xffff);
+       GEN5_IRQ_RESET(GEN8_PCU_);
 
-       I915_WRITE(VLV_IMR, 0xffffffff);
-       I915_WRITE(VLV_IER, 0x0);
-       I915_WRITE(VLV_IIR, 0xffffffff);
-       POSTING_READ(VLV_IIR);
+       vlv_display_irq_uninstall(dev_priv);
 }
 
 static void ironlake_irq_uninstall(struct drm_device *dev)
@@ -4120,9 +3760,9 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                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_ERROR("pipe %c underrun\n", pipe_name(pipe));
+                       if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                               intel_cpu_fifo_underrun_irq_handler(dev_priv,
+                                                                   pipe);
                }
 
                iir = new_iir;
@@ -4314,9 +3954,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                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_ERROR("pipe %c underrun\n", pipe_name(pipe));
+                       if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                               intel_cpu_fifo_underrun_irq_handler(dev_priv,
+                                                                   pipe);
                }
 
                if (blc_event || (iir & I915_ASLE_INTERRUPT))
@@ -4542,9 +4182,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                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_ERROR("pipe %c underrun\n", pipe_name(pipe));
+                       if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                               intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
                }
 
                if (blc_event || (iir & I915_ASLE_INTERRUPT))
This page took 0.039595 seconds and 5 git commands to generate.