These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / i915 / i915_irq.c
index b0df8d1..80a1db0 100644 (file)
  * and related files, but that will be described in separate chapters.
  */
 
+static const u32 hpd_ilk[HPD_NUM_PINS] = {
+       [HPD_PORT_A] = DE_DP_A_HOTPLUG,
+};
+
+static const u32 hpd_ivb[HPD_NUM_PINS] = {
+       [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
+};
+
+static const u32 hpd_bdw[HPD_NUM_PINS] = {
+       [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG,
+};
+
 static const u32 hpd_ibx[HPD_NUM_PINS] = {
        [HPD_CRT] = SDE_CRT_HOTPLUG,
        [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
@@ -61,6 +73,14 @@ static const u32 hpd_cpt[HPD_NUM_PINS] = {
        [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
 };
 
+static const u32 hpd_spt[HPD_NUM_PINS] = {
+       [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
+       [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
+       [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
+       [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
+       [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT
+};
+
 static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_EN,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
@@ -79,7 +99,7 @@ static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
-static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are the same */
+static const u32 hpd_status_i915[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
@@ -88,6 +108,13 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are th
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
+/* BXT hpd list */
+static const u32 hpd_bxt[HPD_NUM_PINS] = {
+       [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA,
+       [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB,
+       [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC
+};
+
 /* IIR can theoretically queue up two events. Be paranoid. */
 #define GEN8_IRQ_RESET_NDX(type, which) do { \
        I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
@@ -112,27 +139,30 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are th
 /*
  * We should clear IMR at preinstall/uninstall, and just check at postinstall.
  */
-#define GEN5_ASSERT_IIR_IS_ZERO(reg) do { \
-       u32 val = I915_READ(reg); \
-       if (val) { \
-               WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", \
-                    (reg), val); \
-               I915_WRITE((reg), 0xffffffff); \
-               POSTING_READ(reg); \
-               I915_WRITE((reg), 0xffffffff); \
-               POSTING_READ(reg); \
-       } \
-} while (0)
+static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = I915_READ(reg);
+
+       if (val == 0)
+               return;
+
+       WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n",
+            reg, val);
+       I915_WRITE(reg, 0xffffffff);
+       POSTING_READ(reg);
+       I915_WRITE(reg, 0xffffffff);
+       POSTING_READ(reg);
+}
 
 #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
-       GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
+       gen5_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \
        I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
        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); \
+       gen5_assert_iir_is_zero(dev_priv, type##IIR); \
        I915_WRITE(type##IER, (ier_val)); \
        I915_WRITE(type##IMR, (imr_val)); \
        POSTING_READ(type##IMR); \
@@ -141,36 +171,85 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are th
 static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
 
 /* For display hotplug interrupt */
-void
-ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+static inline void
+i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
+                                    uint32_t mask,
+                                    uint32_t bits)
 {
+       uint32_t val;
+
        assert_spin_locked(&dev_priv->irq_lock);
+       WARN_ON(bits & ~mask);
 
-       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
-               return;
+       val = I915_READ(PORT_HOTPLUG_EN);
+       val &= ~mask;
+       val |= bits;
+       I915_WRITE(PORT_HOTPLUG_EN, val);
+}
 
-       if ((dev_priv->irq_mask & mask) != 0) {
-               dev_priv->irq_mask &= ~mask;
-               I915_WRITE(DEIMR, dev_priv->irq_mask);
-               POSTING_READ(DEIMR);
-       }
+/**
+ * i915_hotplug_interrupt_update - update hotplug interrupt enable
+ * @dev_priv: driver private
+ * @mask: bits to update
+ * @bits: bits to enable
+ * NOTE: the HPD enable bits are modified both inside and outside
+ * of an interrupt context. To avoid that read-modify-write cycles
+ * interfer, these bits are protected by a spinlock. Since this
+ * function is usually not called from a context where the lock is
+ * held already, this function acquires the lock itself. A non-locking
+ * version is also available.
+ */
+void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
+                                  uint32_t mask,
+                                  uint32_t bits)
+{
+       spin_lock_irq(&dev_priv->irq_lock);
+       i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
+       spin_unlock_irq(&dev_priv->irq_lock);
 }
 
-void
-ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+/**
+ * ilk_update_display_irq - update DEIMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+static void ilk_update_display_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);
 
+       WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
        if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
-       if ((dev_priv->irq_mask & mask) != mask) {
-               dev_priv->irq_mask |= mask;
+       new_val = dev_priv->irq_mask;
+       new_val &= ~interrupt_mask;
+       new_val |= (~enabled_irq_mask & interrupt_mask);
+
+       if (new_val != dev_priv->irq_mask) {
+               dev_priv->irq_mask = new_val;
                I915_WRITE(DEIMR, dev_priv->irq_mask);
                POSTING_READ(DEIMR);
        }
 }
 
+void
+ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+{
+       ilk_update_display_irq(dev_priv, mask, mask);
+}
+
+void
+ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
+{
+       ilk_update_display_irq(dev_priv, mask, 0);
+}
+
 /**
  * ilk_update_gt_irq - update GTIMR
  * @dev_priv: driver private
@@ -337,6 +416,38 @@ void gen6_disable_rps_interrupts(struct drm_device *dev)
        synchronize_irq(dev->irq);
 }
 
+/**
+  * bdw_update_port_irq - update DE port interrupt
+  * @dev_priv: driver private
+  * @interrupt_mask: mask of interrupt bits to update
+  * @enabled_irq_mask: mask of interrupt bits to enable
+  */
+static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
+                               uint32_t interrupt_mask,
+                               uint32_t enabled_irq_mask)
+{
+       uint32_t new_val;
+       uint32_t old_val;
+
+       assert_spin_locked(&dev_priv->irq_lock);
+
+       WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
+               return;
+
+       old_val = I915_READ(GEN8_DE_PORT_IMR);
+
+       new_val = old_val;
+       new_val &= ~interrupt_mask;
+       new_val |= (~enabled_irq_mask & interrupt_mask);
+
+       if (new_val != old_val) {
+               I915_WRITE(GEN8_DE_PORT_IMR, new_val);
+               POSTING_READ(GEN8_DE_PORT_IMR);
+       }
+}
+
 /**
  * ibx_display_interrupt_update - update SDEIMR
  * @dev_priv: driver private
@@ -473,6 +584,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 
 /**
  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
+ * @dev: drm device
  */
 static void i915_enable_asle_pipestat(struct drm_device *dev)
 {
@@ -541,7 +653,7 @@ static void i915_enable_asle_pipestat(struct drm_device *dev)
  *   of horizontal active on the first line of vertical active
  */
 
-static u32 i8xx_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i8xx_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
 {
        /* Gen2 doesn't have a hardware frame counter */
        return 0;
@@ -550,7 +662,7 @@ static u32 i8xx_get_vblank_counter(struct drm_device *dev, int pipe)
 /* Called from drm generic code, passed a 'crtc', which
  * we use as a pipe index
  */
-static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long high_frame;
@@ -558,8 +670,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
        u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-       const struct drm_display_mode *mode =
-               &intel_crtc->config->base.adjusted_mode;
+       const struct drm_display_mode *mode = &intel_crtc->base.hwmode;
 
        htotal = mode->crtc_htotal;
        hsync_start = mode->crtc_hsync_start;
@@ -599,12 +710,11 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
        return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
 }
 
-static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int reg = PIPE_FRMCOUNT_GM45(pipe);
 
-       return I915_READ(reg);
+       return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
 }
 
 /* raw reads, only for fast reads of display block, no need for forcewake etc. */
@@ -614,7 +724,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
+       const struct drm_display_mode *mode = &crtc->base.hwmode;
        enum pipe pipe = crtc->pipe;
        int position, vtotal;
 
@@ -627,6 +737,32 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        else
                position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
 
+       /*
+        * On HSW, the DSL reg (0x70000) appears to return 0 if we
+        * read it just before the start of vblank.  So try it again
+        * so we don't accidentally end up spanning a vblank frame
+        * increment, causing the pipe_update_end() code to squak at us.
+        *
+        * The nature of this problem means we can't simply check the ISR
+        * bit and return the vblank start value; nor can we use the scanline
+        * debug register in the transcoder as it appears to have the same
+        * problem.  We may need to extend this to include other platforms,
+        * but so far testing only shows the problem on HSW.
+        */
+       if (HAS_DDI(dev) && !position) {
+               int i, temp;
+
+               for (i = 0; i < 100; i++) {
+                       udelay(1);
+                       temp = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
+                               DSL_LINEMASK_GEN3;
+                       if (temp != position) {
+                               position = temp;
+                               break;
+                       }
+               }
+       }
+
        /*
         * See update_scanline_offset() for the details on the
         * scanline_offset adjustment.
@@ -634,21 +770,21 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        return (position + crtc->scanline_offset) % vtotal;
 }
 
-static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
                                    unsigned int flags, int *vpos, int *hpos,
-                                   ktime_t *stime, ktime_t *etime)
+                                   ktime_t *stime, ktime_t *etime,
+                                   const struct drm_display_mode *mode)
 {
        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);
-       const struct drm_display_mode *mode = &intel_crtc->config->base.adjusted_mode;
        int position;
        int vbl_start, vbl_end, hsync_start, htotal, vtotal;
        bool in_vbl = true;
        int ret = 0;
        unsigned long irqflags;
 
-       if (!intel_crtc->active) {
+       if (WARN_ON(!mode->crtc_clock)) {
                DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
                                 "pipe %c\n", pipe_name(pipe));
                return 0;
@@ -676,6 +812,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
        /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
+       preempt_disable_rt();
 
        /* Get optional system timestamp before query. */
        if (stime)
@@ -727,6 +864,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
                *etime = ktime_get();
 
        /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
+       preempt_enable_rt();
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
@@ -771,179 +909,34 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc)
        return position;
 }
 
-static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
+static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
                              int *max_error,
                              struct timeval *vblank_time,
                              unsigned flags)
 {
        struct drm_crtc *crtc;
 
-       if (pipe < 0 || pipe >= INTEL_INFO(dev)->num_pipes) {
-               DRM_ERROR("Invalid crtc %d\n", pipe);
+       if (pipe >= INTEL_INFO(dev)->num_pipes) {
+               DRM_ERROR("Invalid crtc %u\n", pipe);
                return -EINVAL;
        }
 
        /* Get drm_crtc to timestamp: */
        crtc = intel_get_crtc_for_pipe(dev, pipe);
        if (crtc == NULL) {
-               DRM_ERROR("Invalid crtc %d\n", pipe);
+               DRM_ERROR("Invalid crtc %u\n", pipe);
                return -EINVAL;
        }
 
-       if (!crtc->state->enable) {
-               DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
+       if (!crtc->hwmode.crtc_clock) {
+               DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
                return -EBUSY;
        }
 
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
                                                     vblank_time, flags,
-                                                    crtc,
-                                                    &to_intel_crtc(crtc)->config->base.adjusted_mode);
-}
-
-static bool intel_hpd_irq_event(struct drm_device *dev,
-                               struct drm_connector *connector)
-{
-       enum drm_connector_status old_status;
-
-       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
-       old_status = connector->status;
-
-       connector->status = connector->funcs->detect(connector, false);
-       if (old_status == connector->status)
-               return false;
-
-       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
-                     connector->base.id,
-                     connector->name,
-                     drm_get_connector_status_name(old_status),
-                     drm_get_connector_status_name(connector->status));
-
-       return true;
-}
-
-static void i915_digport_work_func(struct work_struct *work)
-{
-       struct drm_i915_private *dev_priv =
-               container_of(work, struct drm_i915_private, dig_port_work);
-       u32 long_port_mask, short_port_mask;
-       struct intel_digital_port *intel_dig_port;
-       int i;
-       u32 old_bits = 0;
-
-       spin_lock_irq(&dev_priv->irq_lock);
-       long_port_mask = dev_priv->long_hpd_port_mask;
-       dev_priv->long_hpd_port_mask = 0;
-       short_port_mask = dev_priv->short_hpd_port_mask;
-       dev_priv->short_hpd_port_mask = 0;
-       spin_unlock_irq(&dev_priv->irq_lock);
-
-       for (i = 0; i < I915_MAX_PORTS; i++) {
-               bool valid = false;
-               bool long_hpd = false;
-               intel_dig_port = dev_priv->hpd_irq_port[i];
-               if (!intel_dig_port || !intel_dig_port->hpd_pulse)
-                       continue;
-
-               if (long_port_mask & (1 << i))  {
-                       valid = true;
-                       long_hpd = true;
-               } else if (short_port_mask & (1 << i))
-                       valid = true;
-
-               if (valid) {
-                       enum irqreturn ret;
-
-                       ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);
-                       if (ret == IRQ_NONE) {
-                               /* fall back to old school hpd */
-                               old_bits |= (1 << intel_dig_port->base.hpd_pin);
-                       }
-               }
-       }
-
-       if (old_bits) {
-               spin_lock_irq(&dev_priv->irq_lock);
-               dev_priv->hpd_event_bits |= old_bits;
-               spin_unlock_irq(&dev_priv->irq_lock);
-               schedule_work(&dev_priv->hotplug_work);
-       }
-}
-
-/*
- * Handle hotplug events outside the interrupt handler proper.
- */
-#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
-
-static void i915_hotplug_work_func(struct work_struct *work)
-{
-       struct drm_i915_private *dev_priv =
-               container_of(work, struct drm_i915_private, hotplug_work);
-       struct drm_device *dev = dev_priv->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_connector *intel_connector;
-       struct intel_encoder *intel_encoder;
-       struct drm_connector *connector;
-       bool hpd_disabled = false;
-       bool changed = false;
-       u32 hpd_event_bits;
-
-       mutex_lock(&mode_config->mutex);
-       DRM_DEBUG_KMS("running encoder hotplug functions\n");
-
-       spin_lock_irq(&dev_priv->irq_lock);
-
-       hpd_event_bits = dev_priv->hpd_event_bits;
-       dev_priv->hpd_event_bits = 0;
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               intel_connector = to_intel_connector(connector);
-               if (!intel_connector->encoder)
-                       continue;
-               intel_encoder = intel_connector->encoder;
-               if (intel_encoder->hpd_pin > HPD_NONE &&
-                   dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
-                   connector->polled == DRM_CONNECTOR_POLL_HPD) {
-                       DRM_INFO("HPD interrupt storm detected on connector %s: "
-                                "switching from hotplug detection to polling\n",
-                               connector->name);
-                       dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark = HPD_DISABLED;
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT
-                               | DRM_CONNECTOR_POLL_DISCONNECT;
-                       hpd_disabled = true;
-               }
-               if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
-                       DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
-                                     connector->name, intel_encoder->hpd_pin);
-               }
-       }
-        /* if there were no outputs to poll, poll was disabled,
-         * therefore make sure it's enabled when disabling HPD on
-         * some connectors */
-       if (hpd_disabled) {
-               drm_kms_helper_poll_enable(dev);
-               mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work,
-                                msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
-       }
-
-       spin_unlock_irq(&dev_priv->irq_lock);
-
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               intel_connector = to_intel_connector(connector);
-               if (!intel_connector->encoder)
-                       continue;
-               intel_encoder = intel_connector->encoder;
-               if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
-                       if (intel_encoder->hot_plug)
-                               intel_encoder->hot_plug(intel_encoder);
-                       if (intel_hpd_irq_event(dev, connector))
-                               changed = true;
-               }
-       }
-       mutex_unlock(&mode_config->mutex);
-
-       if (changed)
-               drm_kms_helper_hotplug_event(dev);
+                                                    &crtc->hwmode);
 }
 
 static void ironlake_rps_change_irq_handler(struct drm_device *dev)
@@ -985,8 +978,7 @@ static void ironlake_rps_change_irq_handler(struct drm_device *dev)
        return;
 }
 
-static void notify_ring(struct drm_device *dev,
-                       struct intel_engine_cs *ring)
+static void notify_ring(struct intel_engine_cs *ring)
 {
        if (!intel_ring_initialized(ring))
                return;
@@ -1010,12 +1002,16 @@ static bool vlv_c0_above(struct drm_i915_private *dev_priv,
                         int threshold)
 {
        u64 time, c0;
+       unsigned int mul = 100;
 
        if (old->cz_clock == 0)
                return false;
 
+       if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
+               mul <<= 8;
+
        time = now->cz_clock - old->cz_clock;
-       time *= threshold * dev_priv->mem_freq;
+       time *= threshold * dev_priv->czclk_freq;
 
        /* Workload can be split between render + media, e.g. SwapBuffers
         * being blitted in X after being rendered in mesa. To account for
@@ -1023,7 +1019,7 @@ static bool vlv_c0_above(struct drm_i915_private *dev_priv,
         */
        c0 = now->render_c0 - old->render_c0;
        c0 += now->media_c0 - old->media_c0;
-       c0 *= 100 * VLV_CZ_CLOCK_TO_MILLI_SEC * 4 / 1000;
+       c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
 
        return c0 >= time;
 }
@@ -1049,7 +1045,7 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
        if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
                if (!vlv_c0_above(dev_priv,
                                  &dev_priv->rps.down_ei, &now,
-                                 VLV_RP_DOWN_EI_THRESHOLD))
+                                 dev_priv->rps.down_threshold))
                        events |= GEN6_PM_RP_DOWN_THRESHOLD;
                dev_priv->rps.down_ei = now;
        }
@@ -1057,7 +1053,7 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
        if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
                if (vlv_c0_above(dev_priv,
                                 &dev_priv->rps.up_ei, &now,
-                                VLV_RP_UP_EI_THRESHOLD))
+                                dev_priv->rps.up_threshold))
                        events |= GEN6_PM_RP_UP_THRESHOLD;
                dev_priv->rps.up_ei = now;
        }
@@ -1065,12 +1061,25 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
        return events;
 }
 
+static bool any_waiters(struct drm_i915_private *dev_priv)
+{
+       struct intel_engine_cs *ring;
+       int i;
+
+       for_each_ring(ring, dev_priv, i)
+               if (ring->irq_refcount)
+                       return true;
+
+       return false;
+}
+
 static void gen6_pm_rps_work(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
                container_of(work, struct drm_i915_private, rps.work);
+       bool client_boost;
+       int new_delay, adj, min, max;
        u32 pm_iir;
-       int new_delay, adj;
 
        spin_lock_irq(&dev_priv->irq_lock);
        /* Speed up work cancelation during disabling rps interrupts. */
@@ -1082,12 +1091,14 @@ static void gen6_pm_rps_work(struct work_struct *work)
        dev_priv->rps.pm_iir = 0;
        /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
        gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+       client_boost = dev_priv->rps.client_boost;
+       dev_priv->rps.client_boost = false;
        spin_unlock_irq(&dev_priv->irq_lock);
 
        /* Make sure we didn't queue anything we're not going to process. */
        WARN_ON(pm_iir & ~dev_priv->pm_rps_events);
 
-       if ((pm_iir & dev_priv->pm_rps_events) == 0)
+       if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost)
                return;
 
        mutex_lock(&dev_priv->rps.hw_lock);
@@ -1095,21 +1106,28 @@ static void gen6_pm_rps_work(struct work_struct *work)
        pm_iir |= vlv_wa_c0_ei(dev_priv, pm_iir);
 
        adj = dev_priv->rps.last_adj;
-       if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
+       new_delay = dev_priv->rps.cur_freq;
+       min = dev_priv->rps.min_freq_softlimit;
+       max = dev_priv->rps.max_freq_softlimit;
+
+       if (client_boost) {
+               new_delay = dev_priv->rps.max_freq_softlimit;
+               adj = 0;
+       } else if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
                if (adj > 0)
                        adj *= 2;
-               else {
-                       /* CHV needs even encode values */
-                       adj = IS_CHERRYVIEW(dev_priv->dev) ? 2 : 1;
-               }
-               new_delay = dev_priv->rps.cur_freq + adj;
-
+               else /* CHV needs even encode values */
+                       adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1;
                /*
                 * For better performance, jump directly
                 * to RPe if we're below it.
                 */
-               if (new_delay < dev_priv->rps.efficient_freq)
+               if (new_delay < dev_priv->rps.efficient_freq - adj) {
                        new_delay = dev_priv->rps.efficient_freq;
+                       adj = 0;
+               }
+       } else if (any_waiters(dev_priv)) {
+               adj = 0;
        } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
                if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq)
                        new_delay = dev_priv->rps.efficient_freq;
@@ -1119,23 +1137,19 @@ static void gen6_pm_rps_work(struct work_struct *work)
        } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
                if (adj < 0)
                        adj *= 2;
-               else {
-                       /* CHV needs even encode values */
-                       adj = IS_CHERRYVIEW(dev_priv->dev) ? -2 : -1;
-               }
-               new_delay = dev_priv->rps.cur_freq + adj;
+               else /* CHV needs even encode values */
+                       adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1;
        } else { /* unknown event */
-               new_delay = dev_priv->rps.cur_freq;
+               adj = 0;
        }
 
+       dev_priv->rps.last_adj = adj;
+
        /* sysfs frequency interfaces may have snuck in while servicing the
         * interrupt
         */
-       new_delay = clamp_t(int, new_delay,
-                           dev_priv->rps.min_freq_softlimit,
-                           dev_priv->rps.max_freq_softlimit);
-
-       dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_freq;
+       new_delay += adj;
+       new_delay = clamp_t(int, new_delay, min, max);
 
        intel_set_rps(dev_priv->dev, new_delay);
 
@@ -1251,9 +1265,9 @@ static void ilk_gt_irq_handler(struct drm_device *dev,
 {
        if (gt_iir &
            (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-               notify_ring(dev, &dev_priv->ring[RCS]);
+               notify_ring(&dev_priv->ring[RCS]);
        if (gt_iir & ILK_BSD_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[VCS]);
+               notify_ring(&dev_priv->ring[VCS]);
 }
 
 static void snb_gt_irq_handler(struct drm_device *dev,
@@ -1263,11 +1277,11 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 
        if (gt_iir &
            (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-               notify_ring(dev, &dev_priv->ring[RCS]);
+               notify_ring(&dev_priv->ring[RCS]);
        if (gt_iir & GT_BSD_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[VCS]);
+               notify_ring(&dev_priv->ring[VCS]);
        if (gt_iir & GT_BLT_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+               notify_ring(&dev_priv->ring[BCS]);
 
        if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
                      GT_BSD_CS_ERROR_INTERRUPT |
@@ -1278,250 +1292,186 @@ static void snb_gt_irq_handler(struct drm_device *dev,
                ivybridge_parity_error_irq_handler(dev, gt_iir);
 }
 
-static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
-                                      struct drm_i915_private *dev_priv,
+static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
                                       u32 master_ctl)
 {
-       struct intel_engine_cs *ring;
-       u32 rcs, bcs, vcs;
-       uint32_t tmp = 0;
        irqreturn_t ret = IRQ_NONE;
 
        if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
-               tmp = I915_READ(GEN8_GT_IIR(0));
+               u32 tmp = I915_READ_FW(GEN8_GT_IIR(0));
                if (tmp) {
-                       I915_WRITE(GEN8_GT_IIR(0), tmp);
+                       I915_WRITE_FW(GEN8_GT_IIR(0), tmp);
                        ret = IRQ_HANDLED;
 
-                       rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
-                       ring = &dev_priv->ring[RCS];
-                       if (rcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, ring);
-                       if (rcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_lrc_irq_handler(ring);
-
-                       bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
-                       ring = &dev_priv->ring[BCS];
-                       if (bcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, ring);
-                       if (bcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_lrc_irq_handler(ring);
+                       if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
+                               intel_lrc_irq_handler(&dev_priv->ring[RCS]);
+                       if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
+                               notify_ring(&dev_priv->ring[RCS]);
+
+                       if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
+                               intel_lrc_irq_handler(&dev_priv->ring[BCS]);
+                       if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
+                               notify_ring(&dev_priv->ring[BCS]);
                } else
                        DRM_ERROR("The master control interrupt lied (GT0)!\n");
        }
 
        if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
-               tmp = I915_READ(GEN8_GT_IIR(1));
+               u32 tmp = I915_READ_FW(GEN8_GT_IIR(1));
                if (tmp) {
-                       I915_WRITE(GEN8_GT_IIR(1), tmp);
+                       I915_WRITE_FW(GEN8_GT_IIR(1), tmp);
                        ret = IRQ_HANDLED;
 
-                       vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
-                       ring = &dev_priv->ring[VCS];
-                       if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, ring);
-                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_lrc_irq_handler(ring);
-
-                       vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
-                       ring = &dev_priv->ring[VCS2];
-                       if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, ring);
-                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_lrc_irq_handler(ring);
-               } else
-                       DRM_ERROR("The master control interrupt lied (GT1)!\n");
-       }
+                       if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
+                               intel_lrc_irq_handler(&dev_priv->ring[VCS]);
+                       if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
+                               notify_ring(&dev_priv->ring[VCS]);
 
-       if (master_ctl & GEN8_GT_PM_IRQ) {
-               tmp = I915_READ(GEN8_GT_IIR(2));
-               if (tmp & dev_priv->pm_rps_events) {
-                       I915_WRITE(GEN8_GT_IIR(2),
-                                  tmp & dev_priv->pm_rps_events);
-                       ret = IRQ_HANDLED;
-                       gen6_rps_irq_handler(dev_priv, tmp);
+                       if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
+                               intel_lrc_irq_handler(&dev_priv->ring[VCS2]);
+                       if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
+                               notify_ring(&dev_priv->ring[VCS2]);
                } else
-                       DRM_ERROR("The master control interrupt lied (PM)!\n");
+                       DRM_ERROR("The master control interrupt lied (GT1)!\n");
        }
 
        if (master_ctl & GEN8_GT_VECS_IRQ) {
-               tmp = I915_READ(GEN8_GT_IIR(3));
+               u32 tmp = I915_READ_FW(GEN8_GT_IIR(3));
                if (tmp) {
-                       I915_WRITE(GEN8_GT_IIR(3), tmp);
+                       I915_WRITE_FW(GEN8_GT_IIR(3), tmp);
                        ret = IRQ_HANDLED;
 
-                       vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
-                       ring = &dev_priv->ring[VECS];
-                       if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, ring);
-                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_lrc_irq_handler(ring);
+                       if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
+                               intel_lrc_irq_handler(&dev_priv->ring[VECS]);
+                       if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
+                               notify_ring(&dev_priv->ring[VECS]);
                } else
                        DRM_ERROR("The master control interrupt lied (GT3)!\n");
        }
 
+       if (master_ctl & GEN8_GT_PM_IRQ) {
+               u32 tmp = I915_READ_FW(GEN8_GT_IIR(2));
+               if (tmp & dev_priv->pm_rps_events) {
+                       I915_WRITE_FW(GEN8_GT_IIR(2),
+                                     tmp & dev_priv->pm_rps_events);
+                       ret = IRQ_HANDLED;
+                       gen6_rps_irq_handler(dev_priv, tmp);
+               } else
+                       DRM_ERROR("The master control interrupt lied (PM)!\n");
+       }
+
        return ret;
 }
 
-#define HPD_STORM_DETECT_PERIOD 1000
-#define HPD_STORM_THRESHOLD 5
-
-static int pch_port_to_hotplug_shift(enum port port)
+static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
 {
        switch (port) {
        case PORT_A:
+               return val & PORTA_HOTPLUG_LONG_DETECT;
+       case PORT_B:
+               return val & PORTB_HOTPLUG_LONG_DETECT;
+       case PORT_C:
+               return val & PORTC_HOTPLUG_LONG_DETECT;
+       default:
+               return false;
+       }
+}
+
+static bool spt_port_hotplug2_long_detect(enum port port, u32 val)
+{
+       switch (port) {
        case PORT_E:
+               return val & PORTE_HOTPLUG_LONG_DETECT;
        default:
-               return -1;
+               return false;
+       }
+}
+
+static bool spt_port_hotplug_long_detect(enum port port, u32 val)
+{
+       switch (port) {
+       case PORT_A:
+               return val & PORTA_HOTPLUG_LONG_DETECT;
        case PORT_B:
-               return 0;
+               return val & PORTB_HOTPLUG_LONG_DETECT;
        case PORT_C:
-               return 8;
+               return val & PORTC_HOTPLUG_LONG_DETECT;
        case PORT_D:
-               return 16;
+               return val & PORTD_HOTPLUG_LONG_DETECT;
+       default:
+               return false;
        }
 }
 
-static int i915_port_to_hotplug_shift(enum port port)
+static bool ilk_port_hotplug_long_detect(enum port port, u32 val)
 {
        switch (port) {
        case PORT_A:
-       case PORT_E:
+               return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
        default:
-               return -1;
+               return false;
+       }
+}
+
+static bool pch_port_hotplug_long_detect(enum port port, u32 val)
+{
+       switch (port) {
        case PORT_B:
-               return 17;
+               return val & PORTB_HOTPLUG_LONG_DETECT;
        case PORT_C:
-               return 19;
+               return val & PORTC_HOTPLUG_LONG_DETECT;
        case PORT_D:
-               return 21;
+               return val & PORTD_HOTPLUG_LONG_DETECT;
+       default:
+               return false;
        }
 }
 
-static inline enum port get_port_from_pin(enum hpd_pin pin)
+static bool i9xx_port_hotplug_long_detect(enum port port, u32 val)
 {
-       switch (pin) {
-       case HPD_PORT_B:
-               return PORT_B;
-       case HPD_PORT_C:
-               return PORT_C;
-       case HPD_PORT_D:
-               return PORT_D;
+       switch (port) {
+       case PORT_B:
+               return val & PORTB_HOTPLUG_INT_LONG_PULSE;
+       case PORT_C:
+               return val & PORTC_HOTPLUG_INT_LONG_PULSE;
+       case PORT_D:
+               return val & PORTD_HOTPLUG_INT_LONG_PULSE;
        default:
-               return PORT_A; /* no hpd */
+               return false;
        }
 }
 
-static inline void intel_hpd_irq_handler(struct drm_device *dev,
-                                        u32 hotplug_trigger,
-                                        u32 dig_hotplug_reg,
-                                        const u32 hpd[HPD_NUM_PINS])
+/*
+ * Get a bit mask of pins that have triggered, and which ones may be long.
+ * This can be called multiple times with the same masks to accumulate
+ * hotplug detection results from several registers.
+ *
+ * Note that the caller is expected to zero out the masks initially.
+ */
+static void intel_get_hpd_pins(u32 *pin_mask, u32 *long_mask,
+                            u32 hotplug_trigger, u32 dig_hotplug_reg,
+                            const u32 hpd[HPD_NUM_PINS],
+                            bool long_pulse_detect(enum port port, u32 val))
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
        enum port port;
-       bool storm_detected = false;
-       bool queue_dig = false, queue_hp = false;
-       u32 dig_shift;
-       u32 dig_port_mask = 0;
-
-       if (!hotplug_trigger)
-               return;
-
-       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x\n",
-                        hotplug_trigger, dig_hotplug_reg);
+       int i;
 
-       spin_lock(&dev_priv->irq_lock);
-       for (i = 1; i < HPD_NUM_PINS; i++) {
-               if (!(hpd[i] & hotplug_trigger))
+       for_each_hpd_pin(i) {
+               if ((hpd[i] & hotplug_trigger) == 0)
                        continue;
 
-               port = get_port_from_pin(i);
-               if (port && dev_priv->hpd_irq_port[port]) {
-                       bool long_hpd;
-
-                       if (HAS_PCH_SPLIT(dev)) {
-                               dig_shift = pch_port_to_hotplug_shift(port);
-                               long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
-                       } else {
-                               dig_shift = i915_port_to_hotplug_shift(port);
-                               long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
-                       }
-
-                       DRM_DEBUG_DRIVER("digital hpd port %c - %s\n",
-                                        port_name(port),
-                                        long_hpd ? "long" : "short");
-                       /* for long HPD pulses we want to have the digital queue happen,
-                          but we still want HPD storm detection to function. */
-                       if (long_hpd) {
-                               dev_priv->long_hpd_port_mask |= (1 << port);
-                               dig_port_mask |= hpd[i];
-                       } else {
-                               /* for short HPD just trigger the digital queue */
-                               dev_priv->short_hpd_port_mask |= (1 << port);
-                               hotplug_trigger &= ~hpd[i];
-                       }
-                       queue_dig = true;
-               }
-       }
-
-       for (i = 1; i < HPD_NUM_PINS; i++) {
-               if (hpd[i] & hotplug_trigger &&
-                   dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {
-                       /*
-                        * On GMCH platforms the interrupt mask bits only
-                        * prevent irq generation, not the setting of the
-                        * hotplug bits itself. So only WARN about unexpected
-                        * interrupts on saner platforms.
-                        */
-                       WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev),
-                                 "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
-                                 hotplug_trigger, i, hpd[i]);
-
-                       continue;
-               }
+               *pin_mask |= BIT(i);
 
-               if (!(hpd[i] & hotplug_trigger) ||
-                   dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
+               if (!intel_hpd_pin_to_port(i, &port))
                        continue;
 
-               if (!(dig_port_mask & hpd[i])) {
-                       dev_priv->hpd_event_bits |= (1 << i);
-                       queue_hp = true;
-               }
-
-               if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
-                                  dev_priv->hpd_stats[i].hpd_last_jiffies
-                                  + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
-                       dev_priv->hpd_stats[i].hpd_last_jiffies = jiffies;
-                       dev_priv->hpd_stats[i].hpd_cnt = 0;
-                       DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: 0\n", i);
-               } else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
-                       dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
-                       dev_priv->hpd_event_bits &= ~(1 << i);
-                       DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i);
-                       storm_detected = true;
-               } else {
-                       dev_priv->hpd_stats[i].hpd_cnt++;
-                       DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", i,
-                                     dev_priv->hpd_stats[i].hpd_cnt);
-               }
+               if (long_pulse_detect(port, dig_hotplug_reg))
+                       *long_mask |= BIT(i);
        }
 
-       if (storm_detected)
-               dev_priv->display.hpd_irq_setup(dev);
-       spin_unlock(&dev_priv->irq_lock);
+       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x\n",
+                        hotplug_trigger, dig_hotplug_reg, *pin_mask);
 
-       /*
-        * Our hotplug handler can grab modeset locks (by calling down into the
-        * fb helpers). Hence it must not be run on our own dev-priv->wq work
-        * queue for otherwise the flush_work in the pageflip code will
-        * deadlock.
-        */
-       if (queue_dig)
-               queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
-       if (queue_hp)
-               schedule_work(&dev_priv->hotplug_work);
 }
 
 static void gmbus_irq_handler(struct drm_device *dev)
@@ -1654,7 +1604,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
 
        if (HAS_VEBOX(dev_priv->dev)) {
                if (pm_iir & PM_VEBOX_USER_INTERRUPT)
-                       notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
+                       notify_ring(&dev_priv->ring[VECS]);
 
                if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
                        DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
@@ -1746,28 +1696,40 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+       u32 pin_mask = 0, long_mask = 0;
 
-       if (hotplug_status) {
-               I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-               /*
-                * Make sure hotplug status is cleared before we clear IIR, or else we
-                * may miss hotplug events.
-                */
-               POSTING_READ(PORT_HOTPLUG_STAT);
+       if (!hotplug_status)
+               return;
 
-               if (IS_G4X(dev)) {
-                       u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
+       I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+       /*
+        * Make sure hotplug status is cleared before we clear IIR, or else we
+        * may miss hotplug events.
+        */
+       POSTING_READ(PORT_HOTPLUG_STAT);
 
-                       intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_g4x);
-               } else {
-                       u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+       if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+               u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
 
-                       intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_i915);
+               if (hotplug_trigger) {
+                       intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                                          hotplug_trigger, hpd_status_g4x,
+                                          i9xx_port_hotplug_long_detect);
+
+                       intel_hpd_irq_handler(dev, pin_mask, long_mask);
                }
 
-               if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
-                   hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+               if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
                        dp_aux_irq_handler(dev);
+       } else {
+               u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+
+               if (hotplug_trigger) {
+                       intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                                          hotplug_trigger, hpd_status_i915,
+                                          i9xx_port_hotplug_long_detect);
+                       intel_hpd_irq_handler(dev, pin_mask, long_mask);
+               }
        }
 }
 
@@ -1848,7 +1810,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
                        I915_WRITE(VLV_IIR, iir);
                }
 
-               gen8_gt_irq_handler(dev, dev_priv, master_ctl);
+               gen8_gt_irq_handler(dev_priv, master_ctl);
 
                /* Call regardless, as some status bits might not be
                 * signalled in iir */
@@ -1861,17 +1823,30 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
        return ret;
 }
 
+static void ibx_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+                               const u32 hpd[HPD_NUM_PINS])
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+       dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+       I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+       intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                          dig_hotplug_reg, hpd,
+                          pch_port_hotplug_long_detect);
+
+       intel_hpd_irq_handler(dev, pin_mask, long_mask);
+}
+
 static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
        u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
-       u32 dig_hotplug_reg;
 
-       dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
-       I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
-
-       intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_ibx);
+       if (hotplug_trigger)
+               ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
 
        if (pch_iir & SDE_AUDIO_POWER_MASK) {
                int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -1963,12 +1938,9 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
        u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
-       u32 dig_hotplug_reg;
 
-       dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
-       I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
-
-       intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_cpt);
+       if (hotplug_trigger)
+               ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
 
        if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
                int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
@@ -1999,10 +1971,67 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
                cpt_serr_int_handler(dev);
 }
 
+static void spt_irq_handler(struct drm_device *dev, u32 pch_iir)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
+               ~SDE_PORTE_HOTPLUG_SPT;
+       u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
+       u32 pin_mask = 0, long_mask = 0;
+
+       if (hotplug_trigger) {
+               u32 dig_hotplug_reg;
+
+               dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+               I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+               intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                                  dig_hotplug_reg, hpd_spt,
+                                  spt_port_hotplug_long_detect);
+       }
+
+       if (hotplug2_trigger) {
+               u32 dig_hotplug_reg;
+
+               dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2);
+               I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg);
+
+               intel_get_hpd_pins(&pin_mask, &long_mask, hotplug2_trigger,
+                                  dig_hotplug_reg, hpd_spt,
+                                  spt_port_hotplug2_long_detect);
+       }
+
+       if (pin_mask)
+               intel_hpd_irq_handler(dev, pin_mask, long_mask);
+
+       if (pch_iir & SDE_GMBUS_CPT)
+               gmbus_irq_handler(dev);
+}
+
+static void ilk_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+                               const u32 hpd[HPD_NUM_PINS])
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+       dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
+       I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg);
+
+       intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                          dig_hotplug_reg, hpd,
+                          ilk_port_hotplug_long_detect);
+
+       intel_hpd_irq_handler(dev, pin_mask, long_mask);
+}
+
 static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
+       u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
+
+       if (hotplug_trigger)
+               ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ilk);
 
        if (de_iir & DE_AUX_CHANNEL_A)
                dp_aux_irq_handler(dev);
@@ -2052,6 +2081,10 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
+       u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
+
+       if (hotplug_trigger)
+               ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_ivb);
 
        if (de_iir & DE_ERR_INT_IVB)
                ivb_err_int_handler(dev);
@@ -2164,6 +2197,22 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
        return ret;
 }
 
+static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger,
+                               const u32 hpd[HPD_NUM_PINS])
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+       dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+       I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+       intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
+                          dig_hotplug_reg, hpd,
+                          bxt_port_hotplug_long_detect);
+
+       intel_hpd_irq_handler(dev, pin_mask, long_mask);
+}
+
 static irqreturn_t gen8_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -2177,21 +2226,20 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        if (!intel_irqs_enabled(dev_priv))
                return IRQ_NONE;
 
-       if (IS_GEN9(dev))
+       if (INTEL_INFO(dev_priv)->gen >= 9)
                aux_mask |=  GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
                        GEN9_AUX_CHANNEL_D;
 
-       master_ctl = I915_READ(GEN8_MASTER_IRQ);
+       master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
        master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
        if (!master_ctl)
                return IRQ_NONE;
 
-       I915_WRITE(GEN8_MASTER_IRQ, 0);
-       POSTING_READ(GEN8_MASTER_IRQ);
+       I915_WRITE_FW(GEN8_MASTER_IRQ, 0);
 
        /* Find, clear, then process each source of interrupt */
 
-       ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl);
+       ret = gen8_gt_irq_handler(dev_priv, master_ctl);
 
        if (master_ctl & GEN8_DE_MISC_IRQ) {
                tmp = I915_READ(GEN8_DE_MISC_IIR);
@@ -2210,12 +2258,36 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        if (master_ctl & GEN8_DE_PORT_IRQ) {
                tmp = I915_READ(GEN8_DE_PORT_IIR);
                if (tmp) {
+                       bool found = false;
+                       u32 hotplug_trigger = 0;
+
+                       if (IS_BROXTON(dev_priv))
+                               hotplug_trigger = tmp & BXT_DE_PORT_HOTPLUG_MASK;
+                       else if (IS_BROADWELL(dev_priv))
+                               hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG;
+
                        I915_WRITE(GEN8_DE_PORT_IIR, tmp);
                        ret = IRQ_HANDLED;
 
-                       if (tmp & aux_mask)
+                       if (tmp & aux_mask) {
                                dp_aux_irq_handler(dev);
-                       else
+                               found = true;
+                       }
+
+                       if (hotplug_trigger) {
+                               if (IS_BROXTON(dev))
+                                       bxt_hpd_irq_handler(dev, hotplug_trigger, hpd_bxt);
+                               else
+                                       ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_bdw);
+                               found = true;
+                       }
+
+                       if (IS_BROXTON(dev) && (tmp & BXT_DE_PORT_GMBUS)) {
+                               gmbus_irq_handler(dev);
+                               found = true;
+                       }
+
+                       if (!found)
                                DRM_ERROR("Unexpected DE Port interrupt\n");
                }
                else
@@ -2237,7 +2309,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                            intel_pipe_handle_vblank(dev, pipe))
                                intel_check_page_flip(dev, pipe);
 
-                       if (IS_GEN9(dev))
+                       if (INTEL_INFO(dev_priv)->gen >= 9)
                                flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE;
                        else
                                flip_done = pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE;
@@ -2255,7 +2327,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                                                                    pipe);
 
 
-                       if (IS_GEN9(dev))
+                       if (INTEL_INFO(dev_priv)->gen >= 9)
                                fault_errors = pipe_iir & GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
                        else
                                fault_errors = pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
@@ -2268,7 +2340,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                        DRM_ERROR("The master control interrupt lied (DE PIPE)!\n");
        }
 
-       if (!HAS_PCH_NOP(dev) && master_ctl & GEN8_DE_PCH_IRQ) {
+       if (HAS_PCH_SPLIT(dev) && !HAS_PCH_NOP(dev) &&
+           master_ctl & GEN8_DE_PCH_IRQ) {
                /*
                 * FIXME(BDW): Assume for now that the new interrupt handling
                 * scheme also closed the SDE interrupt handling race we've seen
@@ -2278,14 +2351,22 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
                if (pch_iir) {
                        I915_WRITE(SDEIIR, pch_iir);
                        ret = IRQ_HANDLED;
-                       cpt_irq_handler(dev, pch_iir);
-               } else
-                       DRM_ERROR("The master control interrupt lied (SDE)!\n");
 
+                       if (HAS_PCH_SPT(dev_priv))
+                               spt_irq_handler(dev, pch_iir);
+                       else
+                               cpt_irq_handler(dev, pch_iir);
+               } else {
+                       /*
+                        * Like on previous PCH there seems to be something
+                        * fishy going on with forwarding PCH interrupts.
+                        */
+                       DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n");
+               }
        }
 
-       I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
-       POSTING_READ(GEN8_MASTER_IRQ);
+       I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
+       POSTING_READ_FW(GEN8_MASTER_IRQ);
 
        return ret;
 }
@@ -2320,6 +2401,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
 
 /**
  * i915_reset_and_wakeup - do process context error handling work
+ * @dev: drm device
  *
  * Fire an error uevent so userspace can see that a hang or error
  * was detected.
@@ -2390,7 +2472,7 @@ static void i915_reset_and_wakeup(struct drm_device *dev)
                        kobject_uevent_env(&dev->primary->kdev->kobj,
                                           KOBJ_CHANGE, reset_done_event);
                } else {
-                       atomic_set_mask(I915_WEDGED, &error->reset_counter);
+                       atomic_or(I915_WEDGED, &error->reset_counter);
                }
 
                /*
@@ -2497,7 +2579,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
  * i915_handle_error - handle a gpu error
  * @dev: drm device
  *
- * Do some basic checking of regsiter state at error time and
+ * Do some basic checking of register state at error time and
  * dump it to the syslog.  Also call i915_capture_error_state() to make
  * sure we get a record and make it available in debugfs.  Fire a uevent
  * so userspace knows something bad happened (should trigger collection
@@ -2518,7 +2600,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
        i915_report_and_clear_eir(dev);
 
        if (wedged) {
-               atomic_set_mask(I915_RESET_IN_PROGRESS_FLAG,
+               atomic_or(I915_RESET_IN_PROGRESS_FLAG,
                                &dev_priv->gpu_error.reset_counter);
 
                /*
@@ -2543,7 +2625,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-static int i915_enable_vblank(struct drm_device *dev, int pipe)
+static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2560,7 +2642,7 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
        return 0;
 }
 
-static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2574,7 +2656,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
        return 0;
 }
 
-static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
+static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2587,7 +2669,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
        return 0;
 }
 
-static int gen8_enable_vblank(struct drm_device *dev, int pipe)
+static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2603,7 +2685,7 @@ static int gen8_enable_vblank(struct drm_device *dev, int pipe)
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-static void i915_disable_vblank(struct drm_device *dev, int pipe)
+static void i915_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2615,7 +2697,7 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2627,7 +2709,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
+static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2638,7 +2720,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static void gen8_disable_vblank(struct drm_device *dev, int pipe)
+static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -2710,6 +2792,26 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
        u64 offset = 0;
        int i, backwards;
 
+       /*
+        * This function does not support execlist mode - any attempt to
+        * proceed further into this function will result in a kernel panic
+        * when dereferencing ring->buffer, which is not set up in execlist
+        * mode.
+        *
+        * The correct way of doing it would be to derive the currently
+        * executing ring buffer from the current context, which is derived
+        * from the currently running request. Unfortunately, to get the
+        * current request we would have to grab the struct_mutex before doing
+        * anything else, which would be ill-advised since some other thread
+        * might have grabbed it already and managed to hang itself, causing
+        * the hang checker to deadlock.
+        *
+        * Therefore, this function does not support execlist mode in its
+        * current form. Just return NULL and move on.
+        */
+       if (ring->buffer == NULL)
+               return NULL;
+
        ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
        if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
                return NULL;
@@ -3044,7 +3146,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
 {
        enum pipe pipe;
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       i915_hotplug_interrupt_update(dev_priv, 0xFFFFFFFF, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
        for_each_pipe(dev_priv, pipe)
@@ -3097,7 +3199,8 @@ static void gen8_irq_reset(struct drm_device *dev)
        GEN5_IRQ_RESET(GEN8_DE_MISC_);
        GEN5_IRQ_RESET(GEN8_PCU_);
 
-       ibx_irq_reset(dev);
+       if (HAS_PCH_SPLIT(dev))
+               ibx_irq_reset(dev);
 }
 
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
@@ -3137,37 +3240,123 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
        vlv_display_irq_reset(dev_priv);
 }
 
+static u32 intel_hpd_enabled_irqs(struct drm_device *dev,
+                                 const u32 hpd[HPD_NUM_PINS])
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_encoder *encoder;
+       u32 enabled_irqs = 0;
+
+       for_each_intel_encoder(dev, encoder)
+               if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
+                       enabled_irqs |= hpd[encoder->hpd_pin];
+
+       return enabled_irqs;
+}
+
 static void ibx_hpd_irq_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_encoder *intel_encoder;
-       u32 hotplug_irqs, hotplug, enabled_irqs = 0;
+       u32 hotplug_irqs, hotplug, enabled_irqs;
 
        if (HAS_PCH_IBX(dev)) {
                hotplug_irqs = SDE_HOTPLUG_MASK;
-               for_each_intel_encoder(dev, intel_encoder)
-                       if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-                               enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
+               enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ibx);
        } else {
                hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
-               for_each_intel_encoder(dev, intel_encoder)
-                       if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-                               enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin];
+               enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_cpt);
        }
 
        ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
 
        /*
         * Enable digital hotplug on the PCH, and configure the DP short pulse
-        * duration to 2ms (which is the minimum in the Display Port spec)
-        *
-        * This register is the same on all known PCH chips.
+        * duration to 2ms (which is the minimum in the Display Port spec).
+        * The pulse duration bits are reserved on LPT+.
         */
        hotplug = I915_READ(PCH_PORT_HOTPLUG);
        hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
        hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
        hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
        hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+       /*
+        * When CPU and PCH are on the same package, port A
+        * HPD must be enabled in both north and south.
+        */
+       if (HAS_PCH_LPT_LP(dev))
+               hotplug |= PORTA_HOTPLUG_ENABLE;
+       I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+}
+
+static void spt_hpd_irq_setup(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 hotplug_irqs, hotplug, enabled_irqs;
+
+       hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
+       enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_spt);
+
+       ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+       /* Enable digital hotplug on the PCH */
+       hotplug = I915_READ(PCH_PORT_HOTPLUG);
+       hotplug |= PORTD_HOTPLUG_ENABLE | PORTC_HOTPLUG_ENABLE |
+               PORTB_HOTPLUG_ENABLE | PORTA_HOTPLUG_ENABLE;
+       I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+
+       hotplug = I915_READ(PCH_PORT_HOTPLUG2);
+       hotplug |= PORTE_HOTPLUG_ENABLE;
+       I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
+}
+
+static void ilk_hpd_irq_setup(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 hotplug_irqs, hotplug, enabled_irqs;
+
+       if (INTEL_INFO(dev)->gen >= 8) {
+               hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG;
+               enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bdw);
+
+               bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+       } else if (INTEL_INFO(dev)->gen >= 7) {
+               hotplug_irqs = DE_DP_A_HOTPLUG_IVB;
+               enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ivb);
+
+               ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
+       } else {
+               hotplug_irqs = DE_DP_A_HOTPLUG;
+               enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_ilk);
+
+               ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
+       }
+
+       /*
+        * Enable digital hotplug on the CPU, and configure the DP short pulse
+        * duration to 2ms (which is the minimum in the Display Port spec)
+        * The pulse duration bits are reserved on HSW+.
+        */
+       hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
+       hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK;
+       hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_2ms;
+       I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
+
+       ibx_hpd_irq_setup(dev);
+}
+
+static void bxt_hpd_irq_setup(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 hotplug_irqs, hotplug, enabled_irqs;
+
+       enabled_irqs = intel_hpd_enabled_irqs(dev, hpd_bxt);
+       hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK;
+
+       bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+
+       hotplug = I915_READ(PCH_PORT_HOTPLUG);
+       hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE |
+               PORTA_HOTPLUG_ENABLE;
        I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 }
 
@@ -3184,7 +3373,7 @@ static void ibx_irq_postinstall(struct drm_device *dev)
        else
                mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
 
-       GEN5_ASSERT_IIR_IS_ZERO(SDEIIR);
+       gen5_assert_iir_is_zero(dev_priv, SDEIIR);
        I915_WRITE(SDEIMR, ~mask);
 }
 
@@ -3236,15 +3425,17 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
                                DE_PLANEB_FLIP_DONE_IVB |
                                DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
                extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
-                             DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
+                             DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
+                             DE_DP_A_HOTPLUG_IVB);
        } else {
                display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
                                DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
                                DE_AUX_CHANNEL_A |
                                DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE |
                                DE_POISON);
-               extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT |
-                               DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN;
+               extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT |
+                             DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
+                             DE_DP_A_HOTPLUG);
        }
 
        dev_priv->irq_mask = ~display_mask;
@@ -3371,7 +3562,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
 {
        dev_priv->irq_mask = ~0;
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
        POSTING_READ(PORT_HOTPLUG_EN);
 
        I915_WRITE(VLV_IIR, 0xffffffff);
@@ -3440,21 +3631,31 @@ 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;
+       u32 de_port_masked = GEN8_AUX_CHANNEL_A;
+       u32 de_port_enables;
+       enum pipe pipe;
 
-       if (IS_GEN9(dev_priv)) {
+       if (INTEL_INFO(dev_priv)->gen >= 9) {
                de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE |
                                  GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
-               aux_en |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
-                       GEN9_AUX_CHANNEL_D;
-       } else
+               de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
+                                 GEN9_AUX_CHANNEL_D;
+               if (IS_BROXTON(dev_priv))
+                       de_port_masked |= BXT_DE_PORT_GMBUS;
+       } else {
                de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE |
                                  GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
+       }
 
        de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
                                           GEN8_PIPE_FIFO_UNDERRUN;
 
+       de_port_enables = de_port_masked;
+       if (IS_BROXTON(dev_priv))
+               de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
+       else if (IS_BROADWELL(dev_priv))
+               de_port_enables |= GEN8_PORT_DP_A_HOTPLUG;
+
        dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked;
        dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
        dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
@@ -3466,19 +3667,21 @@ 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_, ~aux_en, aux_en);
+       GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       ibx_irq_pre_postinstall(dev);
+       if (HAS_PCH_SPLIT(dev))
+               ibx_irq_pre_postinstall(dev);
 
        gen8_gt_irq_postinstall(dev_priv);
        gen8_de_irq_postinstall(dev_priv);
 
-       ibx_irq_postinstall(dev);
+       if (HAS_PCH_SPLIT(dev))
+               ibx_irq_postinstall(dev);
 
        I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
        POSTING_READ(GEN8_MASTER_IRQ);
@@ -3687,7 +3890,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                new_iir = I915_READ16(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->ring[RCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
@@ -3733,7 +3936,7 @@ static void i915_irq_preinstall(struct drm_device * dev)
        int pipe;
 
        if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
                I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
        }
 
@@ -3767,7 +3970,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
                I915_USER_INTERRUPT;
 
        if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
                POSTING_READ(PORT_HOTPLUG_EN);
 
                /* Enable in IER... */
@@ -3876,7 +4079,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
                new_iir = I915_READ(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->ring[RCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
@@ -3929,7 +4132,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
        int pipe;
 
        if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
                I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
        }
 
@@ -3950,7 +4153,7 @@ static void i965_irq_preinstall(struct drm_device * dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
        I915_WRITE(HWSTAM, 0xeffe);
@@ -4011,7 +4214,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
        I915_WRITE(IER, enable_mask);
        POSTING_READ(IER);
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
        POSTING_READ(PORT_HOTPLUG_EN);
 
        i915_enable_asle_pipestat(dev);
@@ -4022,29 +4225,27 @@ static int i965_irq_postinstall(struct drm_device *dev)
 static void i915_hpd_irq_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_encoder *intel_encoder;
        u32 hotplug_en;
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= ~HOTPLUG_INT_EN_MASK;
        /* Note HDMI and DP share hotplug bits */
        /* enable bits are the same for all generations */
-       for_each_intel_encoder(dev, intel_encoder)
-               if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-                       hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
+       hotplug_en = intel_hpd_enabled_irqs(dev, hpd_mask_i915);
        /* Programming the CRT detection parameters tends
           to generate a spurious hotplug event about three
           seconds later.  So just do it once.
        */
        if (IS_G4X(dev))
                hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-       hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
        hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
 
        /* Ignore TV since it's buggy */
-       I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+       i915_hotplug_interrupt_update_locked(dev_priv,
+                                            HOTPLUG_INT_EN_MASK |
+                                            CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
+                                            CRT_HOTPLUG_ACTIVATION_PERIOD_64,
+                                            hotplug_en);
 }
 
 static irqreturn_t i965_irq_handler(int irq, void *arg)
@@ -4103,9 +4304,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                new_iir = I915_READ(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->ring[RCS]);
                if (iir & I915_BSD_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[VCS]);
+                       notify_ring(&dev_priv->ring[VCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -4157,7 +4358,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
        if (!dev_priv)
                return;
 
-       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 
        I915_WRITE(HWSTAM, 0xffffffff);
@@ -4172,46 +4373,6 @@ static void i965_irq_uninstall(struct drm_device * dev)
        I915_WRITE(IIR, I915_READ(IIR));
 }
 
-static void intel_hpd_irq_reenable_work(struct work_struct *work)
-{
-       struct drm_i915_private *dev_priv =
-               container_of(work, typeof(*dev_priv),
-                            hotplug_reenable_work.work);
-       struct drm_device *dev = dev_priv->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       int i;
-
-       intel_runtime_pm_get(dev_priv);
-
-       spin_lock_irq(&dev_priv->irq_lock);
-       for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
-               struct drm_connector *connector;
-
-               if (dev_priv->hpd_stats[i].hpd_mark != HPD_DISABLED)
-                       continue;
-
-               dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
-
-               list_for_each_entry(connector, &mode_config->connector_list, head) {
-                       struct intel_connector *intel_connector = to_intel_connector(connector);
-
-                       if (intel_connector->encoder->hpd_pin == i) {
-                               if (connector->polled != intel_connector->polled)
-                                       DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
-                                                        connector->name);
-                               connector->polled = intel_connector->polled;
-                               if (!connector->polled)
-                                       connector->polled = DRM_CONNECTOR_POLL_HPD;
-                       }
-               }
-       }
-       if (dev_priv->display.hpd_irq_setup)
-               dev_priv->display.hpd_irq_setup(dev);
-       spin_unlock_irq(&dev_priv->irq_lock);
-
-       intel_runtime_pm_put(dev_priv);
-}
-
 /**
  * intel_irq_init - initializes irq support
  * @dev_priv: i915 device instance
@@ -4223,8 +4384,8 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
 
-       INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-       INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);
+       intel_hpd_init_work(dev_priv);
+
        INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
        INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
 
@@ -4237,8 +4398,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
 
        INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
                          i915_hangcheck_elapsed);
-       INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work,
-                         intel_hpd_irq_reenable_work);
 
        pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 
@@ -4247,7 +4406,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
        } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
                dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
-               dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+               dev->driver->get_vblank_counter = g4x_get_vblank_counter;
        } else {
                dev->driver->get_vblank_counter = i915_get_vblank_counter;
                dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
@@ -4287,7 +4446,12 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                dev->driver->irq_uninstall = gen8_irq_uninstall;
                dev->driver->enable_vblank = gen8_enable_vblank;
                dev->driver->disable_vblank = gen8_disable_vblank;
-               dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
+               if (IS_BROXTON(dev))
+                       dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
+               else if (HAS_PCH_SPT(dev))
+                       dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;
+               else
+                       dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
        } else if (HAS_PCH_SPLIT(dev)) {
                dev->driver->irq_handler = ironlake_irq_handler;
                dev->driver->irq_preinstall = ironlake_irq_reset;
@@ -4295,7 +4459,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                dev->driver->irq_uninstall = ironlake_irq_uninstall;
                dev->driver->enable_vblank = ironlake_enable_vblank;
                dev->driver->disable_vblank = ironlake_disable_vblank;
-               dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
+               dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
        } else {
                if (INTEL_INFO(dev_priv)->gen == 2) {
                        dev->driver->irq_preinstall = i8xx_irq_preinstall;
@@ -4320,46 +4484,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        }
 }
 
-/**
- * intel_hpd_init - initializes and enables hpd support
- * @dev_priv: i915 device instance
- *
- * This function enables the hotplug support. It requires that interrupts have
- * already been enabled with intel_irq_init_hw(). From this point on hotplug and
- * poll request can run concurrently to other code, so locking rules must be
- * obeyed.
- *
- * This is a separate step from interrupt enabling to simplify the locking rules
- * in the driver load and resume code.
- */
-void intel_hpd_init(struct drm_i915_private *dev_priv)
-{
-       struct drm_device *dev = dev_priv->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
-       int i;
-
-       for (i = 1; i < HPD_NUM_PINS; i++) {
-               dev_priv->hpd_stats[i].hpd_cnt = 0;
-               dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
-       }
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct intel_connector *intel_connector = to_intel_connector(connector);
-               connector->polled = intel_connector->polled;
-               if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
-                       connector->polled = DRM_CONNECTOR_POLL_HPD;
-               if (intel_connector->mst_port)
-                       connector->polled = DRM_CONNECTOR_POLL_HPD;
-       }
-
-       /* Interrupt setup is already guaranteed to be single-threaded, this is
-        * just to make the assert_spin_locked checks happy. */
-       spin_lock_irq(&dev_priv->irq_lock);
-       if (dev_priv->display.hpd_irq_setup)
-               dev_priv->display.hpd_irq_setup(dev);
-       spin_unlock_irq(&dev_priv->irq_lock);
-}
-
 /**
  * intel_irq_install - enables the hardware interrupt
  * @dev_priv: i915 device instance