diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0887581..5689d09 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -256,10 +256,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = IRQ_NONE;
-	u32 de_iir, gt_iir;
+	u32 de_iir, gt_iir, de_ier;
 	u32 new_de_iir, new_gt_iir;
 	struct drm_i915_master_private *master_priv;
 
+	/* disable master interrupt before clearing iir  */
+	de_ier = I915_READ(DEIER);
+	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
+	(void)I915_READ(DEIER);
+
 	de_iir = I915_READ(DEIIR);
 	gt_iir = I915_READ(GTIIR);
 
@@ -292,6 +297,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
 		gt_iir = new_gt_iir;
 	}
 
+	I915_WRITE(DEIER, de_ier);
+	(void)I915_READ(DEIER);
+
 	return ret;
 }
 
@@ -513,6 +521,63 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
 	queue_work(dev_priv->wq, &dev_priv->error_work);
 }
 
+static void i915_handle_hotplug_interrupt(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+	DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
+			 hotplug_status);
+
+	if (!(hotplug_status & dev_priv->hotplug_supported_mask))
+		goto out_ack;
+
+	/* See if this was a spurious interrupt, disable ports if necessary */
+	if (hotplug_status & HDMIB_HOTPLUG_INT_STATUS &&
+	    !(hotplug_status & HDMIB_HOTPLUG_INT_LIVE_STATUS)) {
+		/* spurious event, disable port B */
+		I915_WRITE(HDMIB, I915_READ(HDMIB) & ~PORT_ENABLE);
+	}
+
+	if (hotplug_status & HDMIC_HOTPLUG_INT_STATUS &&
+	    !(hotplug_status & HDMIC_HOTPLUG_INT_LIVE_STATUS)) {
+		/* spurious event, disable port C */
+		I915_WRITE(HDMIC, I915_READ(HDMIC) & ~PORT_ENABLE);
+	}
+
+	if (hotplug_status & HDMID_HOTPLUG_INT_STATUS &&
+	    !(hotplug_status & HDMID_HOTPLUG_INT_LIVE_STATUS)) {
+		/* spurious event, disable port D */
+		I915_WRITE(HDMID, I915_READ(HDMID) & ~PORT_ENABLE);
+	}
+
+	queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+
+	/* EOS interrupts occurs */
+	if (IS_IGD(dev) && (hotplug_status & CRT_EOS_INT_STATUS)) {
+		u32 temp;
+
+		DRM_DEBUG_DRIVER("EOS interrupt occurs\n");
+		/* status is already cleared */
+		temp = I915_READ(ADPA);
+		temp &= ~ADPA_DAC_ENABLE;
+		I915_WRITE(ADPA, temp);
+
+		temp = I915_READ(PORT_HOTPLUG_EN);
+		temp &= ~CRT_EOS_INT_EN;
+		I915_WRITE(PORT_HOTPLUG_EN, temp);
+
+		temp = I915_READ(PORT_HOTPLUG_STAT);
+		if (temp & CRT_EOS_INT_STATUS)
+			I915_WRITE(PORT_HOTPLUG_STAT,
+				   CRT_EOS_INT_STATUS);
+	}
+
+out_ack:
+	I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+	I915_READ(PORT_HOTPLUG_STAT);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -582,39 +647,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 
 		/* Consume port.  Then clear IIR or we'll miss events */
 		if ((I915_HAS_HOTPLUG(dev)) &&
-		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
-			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
-
-			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-				  hotplug_status);
-			if (hotplug_status & dev_priv->hotplug_supported_mask)
-				queue_work(dev_priv->wq,
-					   &dev_priv->hotplug_work);
-
-			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-			I915_READ(PORT_HOTPLUG_STAT);
-
-			/* EOS interrupts occurs */
-			if (IS_IGD(dev) &&
-				(hotplug_status & CRT_EOS_INT_STATUS)) {
-				u32 temp;
-
-				DRM_DEBUG_DRIVER("EOS interrupt occurs\n");
-				/* status is already cleared */
-				temp = I915_READ(ADPA);
-				temp &= ~ADPA_DAC_ENABLE;
-				I915_WRITE(ADPA, temp);
-
-				temp = I915_READ(PORT_HOTPLUG_EN);
-				temp &= ~CRT_EOS_INT_EN;
-				I915_WRITE(PORT_HOTPLUG_EN, temp);
-
-				temp = I915_READ(PORT_HOTPLUG_STAT);
-				if (temp & CRT_EOS_INT_STATUS)
-					I915_WRITE(PORT_HOTPLUG_STAT,
-						CRT_EOS_INT_STATUS);
-			}
-		}
+		    (iir & I915_DISPLAY_PORT_INTERRUPT))
+			i915_handle_hotplug_interrupt(dev);
 
 		I915_WRITE(IIR, iir);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 381cd88..10541c9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -881,12 +881,18 @@
 
 
 #define PORT_HOTPLUG_STAT	0x61114
-#define   HDMIB_HOTPLUG_INT_STATUS		(1 << 29)
-#define   DPB_HOTPLUG_INT_STATUS		(1 << 29)
-#define   HDMIC_HOTPLUG_INT_STATUS		(1 << 28)
-#define   DPC_HOTPLUG_INT_STATUS		(1 << 28)
-#define   HDMID_HOTPLUG_INT_STATUS		(1 << 27)
-#define   DPD_HOTPLUG_INT_STATUS		(1 << 27)
+#define   HDMIB_HOTPLUG_INT_LIVE_STATUS		(1 << 29)
+#define   DPB_HOTPLUG_INT_LIVE_STATUS		(1 << 29)
+#define   HDMIC_HOTPLUG_INT_LIVE_STATUS		(1 << 28)
+#define   DPC_HOTPLUG_INT_LIVE_STATUS		(1 << 28)
+#define   HDMID_HOTPLUG_INT_LIVE_STATUS		(1 << 27)
+#define   DPD_HOTPLUG_INT_LIVE_STATUS		(1 << 27)
+#define   HDMIB_HOTPLUG_INT_STATUS		(3 << 21)
+#define   DPB_HOTPLUG_INT_STATUS		(3 << 21)
+#define   HDMIC_HOTPLUG_INT_STATUS		(3 << 19)
+#define   DPC_HOTPLUG_INT_STATUS		(3 << 19)
+#define   HDMID_HOTPLUG_INT_STATUS		(3 << 17)
+#define   DPD_HOTPLUG_INT_STATUS		(3 << 17)
 #define   CRT_EOS_INT_STATUS			(1 << 12)
 #define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
 #define   TV_HOTPLUG_INT_STATUS			(1 << 10)