All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers
@ 2012-04-24 21:59 Chris Wilson
  2012-04-24 21:59 ` [PATCH 02/12] drm/i915: Remove redundant initialisation of per-ring IRQ waitqueues Chris Wilson
                   ` (10 more replies)
  0 siblings, 11 replies; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

Rather than duplicate similar code across the IRQ installers, perform
the initialisation of the workers upfront. This will lead to simpler
teardown and quiescent code as we can assume that the workers have
been initialised.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |   16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 26172ee..5745b2f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1972,10 +1972,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
 
 	atomic_set(&dev_priv->irq_received, 0);
 
-	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
-	if (IS_GEN6(dev) || IS_IVYBRIDGE(dev))
-		INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
 	I915_WRITE(HWSTAM, 0xeffe);
 
@@ -2003,9 +1999,6 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 
 	atomic_set(&dev_priv->irq_received, 0);
 
-	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
-
 	/* VLV magic */
 	I915_WRITE(VLV_IMR, 0);
 	I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
@@ -2274,9 +2267,6 @@ static void i915_driver_irq_preinstall(struct drm_device * dev)
 
 	atomic_set(&dev_priv->irq_received, 0);
 
-	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
-
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -2593,6 +2583,12 @@ static void i8xx_irq_uninstall(struct drm_device * dev)
 
 void intel_irq_init(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
+	INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
+
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) ||
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/12] drm/i915: Remove redundant initialisation of per-ring IRQ waitqueues
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-24 21:59 ` [PATCH 03/12] drm/i915: pending_flip_is_done is gen3, name it so Chris Wilson
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

The waitqueues are already initialised during ring initialisation so
kill the redundant and duplicated code to do so in each generations IRQ
installer.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |   17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5745b2f..78137df 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2053,12 +2053,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 	u32 render_irqs;
 	u32 hotplug_mask;
 
-	DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
-	if (HAS_BSD(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
-	if (HAS_BLT(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
-
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 	dev_priv->irq_mask = ~display_mask;
 
@@ -2128,12 +2122,6 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
 	u32 render_irqs;
 	u32 hotplug_mask;
 
-	DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
-	if (HAS_BSD(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
-	if (HAS_BLT(dev))
-		DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
-
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 	dev_priv->irq_mask = ~display_mask;
 
@@ -2184,11 +2172,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 
 	dev_priv->irq_mask = ~enable_mask;
 
-
-	DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
-	DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
-	DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
-
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/12] drm/i915: pending_flip_is_done is gen3, name it so
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
  2012-04-24 21:59 ` [PATCH 02/12] drm/i915: Remove redundant initialisation of per-ring IRQ waitqueues Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-24 21:59 ` [PATCH 04/12] drm/i915: Duplicate and split the gen3/4 irq handler Chris Wilson
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

And remove the cargo-culted copy from the valleyview irq handler.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_dma.c |    4 ----
 drivers/gpu/drm/i915/i915_drv.h |    2 +-
 drivers/gpu/drm/i915/i915_irq.c |   18 +++++++++---------
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a813f65..1161bf8 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1300,10 +1300,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	if (ret)
 		goto cleanup_vga_client;
 
-	/* IIR "flip pending" bit means done if this bit is set */
-	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
-		dev_priv->flip_pending_is_done = true;
-
 	intel_modeset_init(dev);
 
 	ret = i915_load_gem_init(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c144013..e458b6c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -763,7 +763,7 @@ typedef struct drm_i915_private {
 	struct drm_crtc *plane_to_crtc_mapping[3];
 	struct drm_crtc *pipe_to_crtc_mapping[3];
 	wait_queue_head_t pending_flip_queue;
-	bool flip_pending_is_done;
+	bool gen3_flip_pending_is_done;
 
 	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 78137df..d5bc3d7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -541,17 +541,13 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 		if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) {
 			drm_handle_vblank(dev, 0);
 			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				intel_finish_page_flip(dev, 0);
-			}
+			intel_finish_page_flip(dev, 0);
 		}
 
 		if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) {
 			drm_handle_vblank(dev, 1);
 			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				intel_finish_page_flip(dev, 0);
-			}
+			intel_finish_page_flip(dev, 0);
 		}
 
 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
@@ -1474,13 +1470,13 @@ static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 
 		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
 			intel_prepare_page_flip(dev, 0);
-			if (dev_priv->flip_pending_is_done)
+			if (dev_priv->gen3_flip_pending_is_done)
 				intel_finish_page_flip_plane(dev, 0);
 		}
 
 		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
 			intel_prepare_page_flip(dev, 1);
-			if (dev_priv->flip_pending_is_done)
+			if (dev_priv->gen3_flip_pending_is_done)
 				intel_finish_page_flip_plane(dev, 1);
 		}
 
@@ -1488,7 +1484,7 @@ static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 			if (pipe_stats[pipe] & vblank_status &&
 			    drm_handle_vblank(dev, pipe)) {
 				vblank++;
-				if (!dev_priv->flip_pending_is_done) {
+				if (!dev_priv->gen3_flip_pending_is_done) {
 					i915_pageflip_stall_check(dev, pipe);
 					intel_finish_page_flip(dev, pipe);
 				}
@@ -2572,6 +2568,10 @@ void intel_irq_init(struct drm_device *dev)
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 	INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
+	/* IIR "flip pending" bit means done if this bit is set */
+	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+		dev_priv->gen3_flip_pending_is_done = true;
+
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) ||
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/12] drm/i915: Duplicate and split the gen3/4 irq handler
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
  2012-04-24 21:59 ` [PATCH 02/12] drm/i915: Remove redundant initialisation of per-ring IRQ waitqueues Chris Wilson
  2012-04-24 21:59 ` [PATCH 03/12] drm/i915: pending_flip_is_done is gen3, name it so Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-24 21:59 ` [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3 Chris Wilson
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

In preparation for rewriting the gen3 irq handler.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |  810 ++++++++++++++++++++++++++-------------
 1 file changed, 536 insertions(+), 274 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d5bc3d7..a956b5f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1381,144 +1381,6 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
 	}
 }
 
-static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-{
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct drm_i915_master_private *master_priv;
-	u32 iir, new_iir;
-	u32 pipe_stats[I915_MAX_PIPES];
-	u32 vblank_status;
-	int vblank = 0;
-	unsigned long irqflags;
-	int irq_received;
-	int ret = IRQ_NONE, pipe;
-	bool blc_event = false;
-
-	atomic_inc(&dev_priv->irq_received);
-
-	iir = I915_READ(IIR);
-
-	if (INTEL_INFO(dev)->gen >= 4)
-		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
-	else
-		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
-
-	for (;;) {
-		irq_received = iir != 0;
-
-		/* Can't rely on pipestat interrupt bit in iir as it might
-		 * have been cleared after the pipestat interrupt was received.
-		 * It doesn't set the bit in iir again, but it still produces
-		 * interrupts (for non-MSI).
-		 */
-		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
-			i915_handle_error(dev, false);
-
-		for_each_pipe(pipe) {
-			int reg = PIPESTAT(pipe);
-			pipe_stats[pipe] = I915_READ(reg);
-
-			/*
-			 * Clear the PIPE*STAT regs before the IIR
-			 */
-			if (pipe_stats[pipe] & 0x8000ffff) {
-				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-					DRM_DEBUG_DRIVER("pipe %c underrun\n",
-							 pipe_name(pipe));
-				I915_WRITE(reg, pipe_stats[pipe]);
-				irq_received = 1;
-			}
-		}
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-		if (!irq_received)
-			break;
-
-		ret = IRQ_HANDLED;
-
-		/* 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);
-		}
-
-		I915_WRITE(IIR, iir);
-		new_iir = I915_READ(IIR); /* Flush posted writes */
-
-		if (dev->primary->master) {
-			master_priv = dev->primary->master->driver_priv;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->last_dispatch =
-					READ_BREADCRUMB(dev_priv);
-		}
-
-		if (iir & I915_USER_INTERRUPT)
-			notify_ring(dev, &dev_priv->ring[RCS]);
-		if (iir & I915_BSD_USER_INTERRUPT)
-			notify_ring(dev, &dev_priv->ring[VCS]);
-
-		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
-			intel_prepare_page_flip(dev, 0);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 0);
-		}
-
-		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
-			intel_prepare_page_flip(dev, 1);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 1);
-		}
-
-		for_each_pipe(pipe) {
-			if (pipe_stats[pipe] & vblank_status &&
-			    drm_handle_vblank(dev, pipe)) {
-				vblank++;
-				if (!dev_priv->gen3_flip_pending_is_done) {
-					i915_pageflip_stall_check(dev, pipe);
-					intel_finish_page_flip(dev, pipe);
-				}
-			}
-
-			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
-				blc_event = true;
-		}
-
-
-		if (blc_event || (iir & I915_ASLE_INTERRUPT))
-			intel_opregion_asle_intr(dev);
-
-		/* With MSI, interrupts are only generated when iir
-		 * transitions from zero to nonzero.  If another bit got
-		 * set while we were handling the existing iir bits, then
-		 * we would never get another interrupt.
-		 *
-		 * This is fine on non-MSI as well, as if we hit this path
-		 * we avoid exiting the interrupt handler only to generate
-		 * another one.
-		 *
-		 * Note that for MSI this could cause a stray interrupt report
-		 * if an interrupt landed in the time between writing IIR and
-		 * the posting read.  This should be rare enough to never
-		 * trigger the 99% of 100,000 interrupts test for disabling
-		 * stray interrupts.
-		 */
-		iir = new_iir;
-	}
-
-	return ret;
-}
-
 static int i915_emit_irq(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -2239,106 +2101,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static void i915_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int pipe;
-
-	atomic_set(&dev_priv->irq_received, 0);
-
-	if (I915_HAS_HOTPLUG(dev)) {
-		I915_WRITE(PORT_HOTPLUG_EN, 0);
-		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-	}
-
-	I915_WRITE(HWSTAM, 0xeffe);
-	for_each_pipe(pipe)
-		I915_WRITE(PIPESTAT(pipe), 0);
-	I915_WRITE(IMR, 0xffffffff);
-	I915_WRITE(IER, 0x0);
-	POSTING_READ(IER);
-}
-
-/*
- * Must be called after intel_modeset_init or hotplug interrupts won't be
- * enabled correctly.
- */
-static int i915_driver_irq_postinstall(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
-	u32 error_mask;
-
-	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
-
-	/* Unmask the interrupts that we always want on. */
-	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
-
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
-
-	if (I915_HAS_HOTPLUG(dev)) {
-		/* Enable in IER... */
-		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
-		/* and unmask in IMR */
-		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
-	}
-
-	/*
-	 * Enable some error detection, note the instruction error mask
-	 * bit is reserved, so we leave it masked.
-	 */
-	if (IS_G4X(dev)) {
-		error_mask = ~(GM45_ERROR_PAGE_TABLE |
-			       GM45_ERROR_MEM_PRIV |
-			       GM45_ERROR_CP_PRIV |
-			       I915_ERROR_MEMORY_REFRESH);
-	} else {
-		error_mask = ~(I915_ERROR_PAGE_TABLE |
-			       I915_ERROR_MEMORY_REFRESH);
-	}
-	I915_WRITE(EMR, error_mask);
-
-	I915_WRITE(IMR, dev_priv->irq_mask);
-	I915_WRITE(IER, enable_mask);
-	POSTING_READ(IER);
-
-	if (I915_HAS_HOTPLUG(dev)) {
-		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
-		/* Note HDMI and DP share bits */
-		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
-			hotplug_en |= HDMIB_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
-			hotplug_en |= HDMIC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
-			hotplug_en |= HDMID_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
-			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
-			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
-			hotplug_en |= CRT_HOTPLUG_INT_EN;
-
-			/* 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_50;
-		}
-
-		/* Ignore TV since it's buggy */
-
-		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-	}
-
-	intel_opregion_enable_asle(dev);
-
-	return 0;
-}
-
 static void valleyview_irq_uninstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2387,45 +2149,18 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
 	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
 }
 
-static void i915_driver_irq_uninstall(struct drm_device * dev)
+static void i8xx_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	if (!dev_priv)
-		return;
-
-	dev_priv->vblank_pipe = 0;
-
-	if (I915_HAS_HOTPLUG(dev)) {
-		I915_WRITE(PORT_HOTPLUG_EN, 0);
-		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-	}
+	atomic_set(&dev_priv->irq_received, 0);
 
-	I915_WRITE(HWSTAM, 0xffffffff);
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0);
-	I915_WRITE(IMR, 0xffffffff);
-	I915_WRITE(IER, 0x0);
-
-	for_each_pipe(pipe)
-		I915_WRITE(PIPESTAT(pipe),
-			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
-	I915_WRITE(IIR, I915_READ(IIR));
-}
-
-static void i8xx_irq_preinstall(struct drm_device * dev)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int pipe;
-
-	atomic_set(&dev_priv->irq_received, 0);
-
-	for_each_pipe(pipe)
-		I915_WRITE(PIPESTAT(pipe), 0);
-	I915_WRITE16(IMR, 0xffff);
-	I915_WRITE16(IER, 0x0);
-	POSTING_READ16(IER);
+	I915_WRITE16(IMR, 0xffff);
+	I915_WRITE16(IER, 0x0);
+	POSTING_READ16(IER);
 }
 
 static int i8xx_irq_postinstall(struct drm_device *dev)
@@ -2560,6 +2295,528 @@ static void i8xx_irq_uninstall(struct drm_device * dev)
 	I915_WRITE16(IIR, I915_READ16(IIR));
 }
 
+static void i915_irq_preinstall(struct drm_device * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
+
+	atomic_set(&dev_priv->irq_received, 0);
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
+	I915_WRITE(HWSTAM, 0xeffe);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
+	POSTING_READ(IER);
+}
+
+static int i915_irq_postinstall(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 error_mask;
+
+	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+
+	/* Unmask the interrupts that we always want on. */
+	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
+
+	dev_priv->pipestat[0] = 0;
+	dev_priv->pipestat[1] = 0;
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		/* Enable in IER... */
+		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
+		/* and unmask in IMR */
+		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
+	}
+
+	/*
+	 * Enable some error detection, note the instruction error mask
+	 * bit is reserved, so we leave it masked.
+	 */
+	if (IS_G4X(dev)) {
+		error_mask = ~(GM45_ERROR_PAGE_TABLE |
+			       GM45_ERROR_MEM_PRIV |
+			       GM45_ERROR_CP_PRIV |
+			       I915_ERROR_MEMORY_REFRESH);
+	} else {
+		error_mask = ~(I915_ERROR_PAGE_TABLE |
+			       I915_ERROR_MEMORY_REFRESH);
+	}
+	I915_WRITE(EMR, error_mask);
+
+	I915_WRITE(IMR, dev_priv->irq_mask);
+	I915_WRITE(IER, enable_mask);
+	POSTING_READ(IER);
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+		/* Note HDMI and DP share bits */
+		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMID_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+			hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+			/* 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_50;
+		}
+
+		/* Ignore TV since it's buggy */
+
+		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+	}
+
+	intel_opregion_enable_asle(dev);
+
+	return 0;
+}
+
+static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *) arg;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	struct drm_i915_master_private *master_priv;
+	u32 iir, new_iir;
+	u32 pipe_stats[I915_MAX_PIPES];
+	u32 vblank_status;
+	int vblank = 0;
+	unsigned long irqflags;
+	int irq_received;
+	int ret = IRQ_NONE, pipe;
+	bool blc_event = false;
+
+	atomic_inc(&dev_priv->irq_received);
+
+	iir = I915_READ(IIR);
+
+	if (INTEL_INFO(dev)->gen >= 4)
+		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
+	else
+		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
+
+	for (;;) {
+		irq_received = iir != 0;
+
+		/* Can't rely on pipestat interrupt bit in iir as it might
+		 * have been cleared after the pipestat interrupt was received.
+		 * It doesn't set the bit in iir again, but it still produces
+		 * interrupts (for non-MSI).
+		 */
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+			i915_handle_error(dev, false);
+
+		for_each_pipe(pipe) {
+			int reg = PIPESTAT(pipe);
+			pipe_stats[pipe] = I915_READ(reg);
+
+			/*
+			 * Clear the PIPE*STAT regs before the IIR
+			 */
+			if (pipe_stats[pipe] & 0x8000ffff) {
+				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+					DRM_DEBUG_DRIVER("pipe %c underrun\n",
+							 pipe_name(pipe));
+				I915_WRITE(reg, pipe_stats[pipe]);
+				irq_received = 1;
+			}
+		}
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+		if (!irq_received)
+			break;
+
+		ret = IRQ_HANDLED;
+
+		/* 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);
+		}
+
+		I915_WRITE(IIR, iir);
+		new_iir = I915_READ(IIR); /* Flush posted writes */
+
+		if (dev->primary->master) {
+			master_priv = dev->primary->master->driver_priv;
+			if (master_priv->sarea_priv)
+				master_priv->sarea_priv->last_dispatch =
+					READ_BREADCRUMB(dev_priv);
+		}
+
+		if (iir & I915_USER_INTERRUPT)
+			notify_ring(dev, &dev_priv->ring[RCS]);
+		if (iir & I915_BSD_USER_INTERRUPT)
+			notify_ring(dev, &dev_priv->ring[VCS]);
+
+		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+			intel_prepare_page_flip(dev, 0);
+			if (dev_priv->gen3_flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 0);
+		}
+
+		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+			intel_prepare_page_flip(dev, 1);
+			if (dev_priv->gen3_flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 1);
+		}
+
+		for_each_pipe(pipe) {
+			if (pipe_stats[pipe] & vblank_status &&
+			    drm_handle_vblank(dev, pipe)) {
+				vblank++;
+				if (!dev_priv->gen3_flip_pending_is_done) {
+					i915_pageflip_stall_check(dev, pipe);
+					intel_finish_page_flip(dev, pipe);
+				}
+			}
+
+			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+				blc_event = true;
+		}
+
+
+		if (blc_event || (iir & I915_ASLE_INTERRUPT))
+			intel_opregion_asle_intr(dev);
+
+		/* With MSI, interrupts are only generated when iir
+		 * transitions from zero to nonzero.  If another bit got
+		 * set while we were handling the existing iir bits, then
+		 * we would never get another interrupt.
+		 *
+		 * This is fine on non-MSI as well, as if we hit this path
+		 * we avoid exiting the interrupt handler only to generate
+		 * another one.
+		 *
+		 * Note that for MSI this could cause a stray interrupt report
+		 * if an interrupt landed in the time between writing IIR and
+		 * the posting read.  This should be rare enough to never
+		 * trigger the 99% of 100,000 interrupts test for disabling
+		 * stray interrupts.
+		 */
+		iir = new_iir;
+	}
+
+	return ret;
+}
+
+static void i915_irq_uninstall(struct drm_device * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
+
+	if (!dev_priv)
+		return;
+
+	dev_priv->vblank_pipe = 0;
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
+	I915_WRITE(HWSTAM, 0xffffffff);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
+
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe),
+			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
+	I915_WRITE(IIR, I915_READ(IIR));
+}
+
+static void i965_irq_preinstall(struct drm_device * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
+
+	atomic_set(&dev_priv->irq_received, 0);
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
+	I915_WRITE(HWSTAM, 0xeffe);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
+	POSTING_READ(IER);
+}
+
+static int i965_irq_postinstall(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 error_mask;
+
+	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+
+	/* Unmask the interrupts that we always want on. */
+	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
+
+	dev_priv->pipestat[0] = 0;
+	dev_priv->pipestat[1] = 0;
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		/* Enable in IER... */
+		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
+		/* and unmask in IMR */
+		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
+	}
+
+	/*
+	 * Enable some error detection, note the instruction error mask
+	 * bit is reserved, so we leave it masked.
+	 */
+	if (IS_G4X(dev)) {
+		error_mask = ~(GM45_ERROR_PAGE_TABLE |
+			       GM45_ERROR_MEM_PRIV |
+			       GM45_ERROR_CP_PRIV |
+			       I915_ERROR_MEMORY_REFRESH);
+	} else {
+		error_mask = ~(I915_ERROR_PAGE_TABLE |
+			       I915_ERROR_MEMORY_REFRESH);
+	}
+	I915_WRITE(EMR, error_mask);
+
+	I915_WRITE(IMR, dev_priv->irq_mask);
+	I915_WRITE(IER, enable_mask);
+	POSTING_READ(IER);
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+		/* Note HDMI and DP share bits */
+		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMID_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+			hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+			/* 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_50;
+		}
+
+		/* Ignore TV since it's buggy */
+
+		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+	}
+
+	intel_opregion_enable_asle(dev);
+
+	return 0;
+}
+
+static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *) arg;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	struct drm_i915_master_private *master_priv;
+	u32 iir, new_iir;
+	u32 pipe_stats[I915_MAX_PIPES];
+	u32 vblank_status;
+	int vblank = 0;
+	unsigned long irqflags;
+	int irq_received;
+	int ret = IRQ_NONE, pipe;
+	bool blc_event = false;
+
+	atomic_inc(&dev_priv->irq_received);
+
+	iir = I915_READ(IIR);
+
+	if (INTEL_INFO(dev)->gen >= 4)
+		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
+	else
+		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
+
+	for (;;) {
+		irq_received = iir != 0;
+
+		/* Can't rely on pipestat interrupt bit in iir as it might
+		 * have been cleared after the pipestat interrupt was received.
+		 * It doesn't set the bit in iir again, but it still produces
+		 * interrupts (for non-MSI).
+		 */
+		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+			i915_handle_error(dev, false);
+
+		for_each_pipe(pipe) {
+			int reg = PIPESTAT(pipe);
+			pipe_stats[pipe] = I915_READ(reg);
+
+			/*
+			 * Clear the PIPE*STAT regs before the IIR
+			 */
+			if (pipe_stats[pipe] & 0x8000ffff) {
+				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+					DRM_DEBUG_DRIVER("pipe %c underrun\n",
+							 pipe_name(pipe));
+				I915_WRITE(reg, pipe_stats[pipe]);
+				irq_received = 1;
+			}
+		}
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+		if (!irq_received)
+			break;
+
+		ret = IRQ_HANDLED;
+
+		/* 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);
+		}
+
+		I915_WRITE(IIR, iir);
+		new_iir = I915_READ(IIR); /* Flush posted writes */
+
+		if (dev->primary->master) {
+			master_priv = dev->primary->master->driver_priv;
+			if (master_priv->sarea_priv)
+				master_priv->sarea_priv->last_dispatch =
+					READ_BREADCRUMB(dev_priv);
+		}
+
+		if (iir & I915_USER_INTERRUPT)
+			notify_ring(dev, &dev_priv->ring[RCS]);
+		if (iir & I915_BSD_USER_INTERRUPT)
+			notify_ring(dev, &dev_priv->ring[VCS]);
+
+		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+			intel_prepare_page_flip(dev, 0);
+			if (dev_priv->gen3_flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 0);
+		}
+
+		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+			intel_prepare_page_flip(dev, 1);
+			if (dev_priv->gen3_flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 1);
+		}
+
+		for_each_pipe(pipe) {
+			if (pipe_stats[pipe] & vblank_status &&
+			    drm_handle_vblank(dev, pipe)) {
+				vblank++;
+				if (!dev_priv->gen3_flip_pending_is_done) {
+					i915_pageflip_stall_check(dev, pipe);
+					intel_finish_page_flip(dev, pipe);
+				}
+			}
+
+			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+				blc_event = true;
+		}
+
+
+		if (blc_event || (iir & I915_ASLE_INTERRUPT))
+			intel_opregion_asle_intr(dev);
+
+		/* With MSI, interrupts are only generated when iir
+		 * transitions from zero to nonzero.  If another bit got
+		 * set while we were handling the existing iir bits, then
+		 * we would never get another interrupt.
+		 *
+		 * This is fine on non-MSI as well, as if we hit this path
+		 * we avoid exiting the interrupt handler only to generate
+		 * another one.
+		 *
+		 * Note that for MSI this could cause a stray interrupt report
+		 * if an interrupt landed in the time between writing IIR and
+		 * the posting read.  This should be rare enough to never
+		 * trigger the 99% of 100,000 interrupts test for disabling
+		 * stray interrupts.
+		 */
+		iir = new_iir;
+	}
+
+	return ret;
+}
+
+static void i965_irq_uninstall(struct drm_device * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
+
+	if (!dev_priv)
+		return;
+
+	dev_priv->vblank_pipe = 0;
+
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
+	I915_WRITE(HWSTAM, 0xffffffff);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
+
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe),
+			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
+	I915_WRITE(IIR, I915_READ(IIR));
+}
+
 void intel_irq_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2614,11 +2871,16 @@ void intel_irq_init(struct drm_device *dev)
 			dev->driver->irq_postinstall = i8xx_irq_postinstall;
 			dev->driver->irq_handler = i8xx_irq_handler;
 			dev->driver->irq_uninstall = i8xx_irq_uninstall;
+		} else if (INTEL_INFO(dev)->gen == 3) {
+			dev->driver->irq_preinstall = i915_irq_preinstall;
+			dev->driver->irq_postinstall = i915_irq_postinstall;
+			dev->driver->irq_uninstall = i915_irq_uninstall;
+			dev->driver->irq_handler = i915_irq_handler;
 		} else {
-			dev->driver->irq_preinstall = i915_driver_irq_preinstall;
-			dev->driver->irq_postinstall = i915_driver_irq_postinstall;
-			dev->driver->irq_uninstall = i915_driver_irq_uninstall;
-			dev->driver->irq_handler = i915_driver_irq_handler;
+			dev->driver->irq_preinstall = i965_irq_preinstall;
+			dev->driver->irq_postinstall = i965_irq_postinstall;
+			dev->driver->irq_uninstall = i965_irq_uninstall;
+			dev->driver->irq_handler = i965_irq_handler;
 		}
 		dev->driver->enable_vblank = i915_enable_vblank;
 		dev->driver->disable_vblank = i915_disable_vblank;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (2 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 04/12] drm/i915: Duplicate and split the gen3/4 irq handler Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:48   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine Chris Wilson
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

On later gen3, you are able to select the meaning of the FlipPending
status bit in IIR and change it to FlipDone. This was sometimes done by
the BIOS leading to confusion on just how pageflipping worked on gen3.
Simplify the implementation by using the legacy meaning for all gen3
machines.

Note: this makes all gen3 machines equally broken...

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.h |    1 -
 drivers/gpu/drm/i915/i915_irq.c |   39 +++++++++++----------------------------
 2 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e458b6c..2e45ba5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -763,7 +763,6 @@ typedef struct drm_i915_private {
 	struct drm_crtc *plane_to_crtc_mapping[3];
 	struct drm_crtc *pipe_to_crtc_mapping[3];
 	wait_queue_head_t pending_flip_queue;
-	bool gen3_flip_pending_is_done;
 
 	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a956b5f..2adc27a 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2478,26 +2478,18 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 		if (iir & I915_BSD_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[VCS]);
 
-		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
 			intel_prepare_page_flip(dev, 0);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 0);
-		}
 
-		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
 			intel_prepare_page_flip(dev, 1);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 1);
-		}
 
 		for_each_pipe(pipe) {
 			if (pipe_stats[pipe] & vblank_status &&
 			    drm_handle_vblank(dev, pipe)) {
 				vblank++;
-				if (!dev_priv->gen3_flip_pending_is_done) {
-					i915_pageflip_stall_check(dev, pipe);
-					intel_finish_page_flip(dev, pipe);
-				}
+				i915_pageflip_stall_check(dev, pipe);
+				intel_finish_page_flip(dev, pipe);
 			}
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
@@ -2739,26 +2731,18 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 		if (iir & I915_BSD_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[VCS]);
 
-		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
 			intel_prepare_page_flip(dev, 0);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 0);
-		}
 
-		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
 			intel_prepare_page_flip(dev, 1);
-			if (dev_priv->gen3_flip_pending_is_done)
-				intel_finish_page_flip_plane(dev, 1);
-		}
 
 		for_each_pipe(pipe) {
 			if (pipe_stats[pipe] & vblank_status &&
 			    drm_handle_vblank(dev, pipe)) {
 				vblank++;
-				if (!dev_priv->gen3_flip_pending_is_done) {
-					i915_pageflip_stall_check(dev, pipe);
-					intel_finish_page_flip(dev, pipe);
-				}
+				i915_pageflip_stall_check(dev, pipe);
+				intel_finish_page_flip(dev, pipe);
 			}
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
@@ -2825,10 +2809,6 @@ void intel_irq_init(struct drm_device *dev)
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 	INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
-	/* IIR "flip pending" bit means done if this bit is set */
-	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
-		dev_priv->gen3_flip_pending_is_done = true;
-
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) ||
@@ -2872,6 +2852,9 @@ void intel_irq_init(struct drm_device *dev)
 			dev->driver->irq_handler = i8xx_irq_handler;
 			dev->driver->irq_uninstall = i8xx_irq_uninstall;
 		} else if (INTEL_INFO(dev)->gen == 3) {
+			/* IIR "flip pending" means done if this bit is set */
+			I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
+
 			dev->driver->irq_preinstall = i915_irq_preinstall;
 			dev->driver->irq_postinstall = i915_irq_postinstall;
 			dev->driver->irq_uninstall = i915_irq_uninstall;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (3 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3 Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:49   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 " Chris Wilson
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

And a couple of miscellaneous cleanups to the main body of the IRQ loop;
move per-loop condition variables within the scope of the loop and move
the old DRI1 breadcrumb to the tail of the function and so only execute
it once.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2adc27a..2e84020 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2651,23 +2651,17 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 	struct drm_i915_master_private *master_priv;
 	u32 iir, new_iir;
 	u32 pipe_stats[I915_MAX_PIPES];
-	u32 vblank_status;
-	int vblank = 0;
 	unsigned long irqflags;
 	int irq_received;
 	int ret = IRQ_NONE, pipe;
-	bool blc_event = false;
 
 	atomic_inc(&dev_priv->irq_received);
 
 	iir = I915_READ(IIR);
 
-	if (INTEL_INFO(dev)->gen >= 4)
-		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
-	else
-		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
-
 	for (;;) {
+		bool blc_event = false;
+
 		irq_received = iir != 0;
 
 		/* Can't rely on pipestat interrupt bit in iir as it might
@@ -2719,13 +2713,6 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 		I915_WRITE(IIR, iir);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
-		if (dev->primary->master) {
-			master_priv = dev->primary->master->driver_priv;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->last_dispatch =
-					READ_BREADCRUMB(dev_priv);
-		}
-
 		if (iir & I915_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[RCS]);
 		if (iir & I915_BSD_USER_INTERRUPT)
@@ -2738,9 +2725,8 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 			intel_prepare_page_flip(dev, 1);
 
 		for_each_pipe(pipe) {
-			if (pipe_stats[pipe] & vblank_status &&
+			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
 			    drm_handle_vblank(dev, pipe)) {
-				vblank++;
 				i915_pageflip_stall_check(dev, pipe);
 				intel_finish_page_flip(dev, pipe);
 			}
@@ -2771,6 +2757,13 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 		iir = new_iir;
 	}
 
+	if (dev->primary->master) {
+		master_priv = dev->primary->master->driver_priv;
+		if (master_priv->sarea_priv)
+			master_priv->sarea_priv->last_dispatch =
+				READ_BREADCRUMB(dev_priv);
+	}
+
 	return ret;
 }
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 irq routine
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (4 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:50   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3 Chris Wilson
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

A couple of miscellaneous cleanups as well to move per-loop condition
variables within the scope of the loop and the update of the DRI1
breadcrumb to the tail of the function.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   55 +++++++++------------------------------
 1 file changed, 12 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2e84020..878f1c3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2319,7 +2319,6 @@ static int i915_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
-	u32 error_mask;
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
@@ -2340,16 +2339,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	 * Enable some error detection, note the instruction error mask
 	 * bit is reserved, so we leave it masked.
 	 */
-	if (IS_G4X(dev)) {
-		error_mask = ~(GM45_ERROR_PAGE_TABLE |
-			       GM45_ERROR_MEM_PRIV |
-			       GM45_ERROR_CP_PRIV |
-			       I915_ERROR_MEMORY_REFRESH);
-	} else {
-		error_mask = ~(I915_ERROR_PAGE_TABLE |
-			       I915_ERROR_MEMORY_REFRESH);
-	}
-	I915_WRITE(EMR, error_mask);
+	I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
 
 	I915_WRITE(IMR, dev_priv->irq_mask);
 	I915_WRITE(IER, enable_mask);
@@ -2358,7 +2348,6 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	if (I915_HAS_HOTPLUG(dev)) {
 		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
 
-		/* Note HDMI and DP share bits */
 		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
 			hotplug_en |= HDMIB_HOTPLUG_INT_EN;
 		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
@@ -2371,13 +2360,6 @@ static int i915_irq_postinstall(struct drm_device *dev)
 			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
 		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
 			hotplug_en |= CRT_HOTPLUG_INT_EN;
-
-			/* 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_50;
 		}
 
@@ -2396,26 +2378,17 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct drm_i915_master_private *master_priv;
-	u32 iir, new_iir;
-	u32 pipe_stats[I915_MAX_PIPES];
-	u32 vblank_status;
-	int vblank = 0;
+	u32 iir, new_iir, pipe_stats[I915_MAX_PIPES];
 	unsigned long irqflags;
-	int irq_received;
 	int ret = IRQ_NONE, pipe;
-	bool blc_event = false;
 
 	atomic_inc(&dev_priv->irq_received);
 
 	iir = I915_READ(IIR);
 
-	if (INTEL_INFO(dev)->gen >= 4)
-		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
-	else
-		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
-
 	for (;;) {
-		irq_received = iir != 0;
+		bool blc_event = false;
+		int irq_received = iir != 0;
 
 		/* Can't rely on pipestat interrupt bit in iir as it might
 		 * have been cleared after the pipestat interrupt was received.
@@ -2466,17 +2439,8 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 		I915_WRITE(IIR, iir);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
-		if (dev->primary->master) {
-			master_priv = dev->primary->master->driver_priv;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->last_dispatch =
-					READ_BREADCRUMB(dev_priv);
-		}
-
 		if (iir & I915_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[RCS]);
-		if (iir & I915_BSD_USER_INTERRUPT)
-			notify_ring(dev, &dev_priv->ring[VCS]);
 
 		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
 			intel_prepare_page_flip(dev, 0);
@@ -2485,9 +2449,8 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 			intel_prepare_page_flip(dev, 1);
 
 		for_each_pipe(pipe) {
-			if (pipe_stats[pipe] & vblank_status &&
+			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
 			    drm_handle_vblank(dev, pipe)) {
-				vblank++;
 				i915_pageflip_stall_check(dev, pipe);
 				intel_finish_page_flip(dev, pipe);
 			}
@@ -2496,7 +2459,6 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 				blc_event = true;
 		}
 
-
 		if (blc_event || (iir & I915_ASLE_INTERRUPT))
 			intel_opregion_asle_intr(dev);
 
@@ -2518,6 +2480,13 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 		iir = new_iir;
 	}
 
+	if (dev->primary->master) {
+		master_priv = dev->primary->master->driver_priv;
+		if (master_priv->sarea_priv)
+			master_priv->sarea_priv->last_dispatch =
+				READ_BREADCRUMB(dev_priv);
+	}
+
 	return ret;
 }
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (5 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 " Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:50   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall Chris Wilson
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 878f1c3..a4e074e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2307,7 +2307,7 @@ static void i915_irq_preinstall(struct drm_device * dev)
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 	}
 
-	I915_WRITE(HWSTAM, 0xeffe);
+	I915_WRITE16(HWSTAM, 0xeffe);
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
@@ -2505,7 +2505,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 	}
 
-	I915_WRITE(HWSTAM, 0xffffffff);
+	I915_WRITE16(HWSTAM, 0xffff);
 	for_each_pipe(pipe)
 		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (6 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3 Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:51   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly Chris Wilson
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

Bring the for-each-pipe loops together so that the code is easier on the
eyes.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a4e074e..e5f627f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2495,9 +2495,6 @@ static void i915_irq_uninstall(struct drm_device * dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
-	if (!dev_priv)
-		return;
-
 	dev_priv->vblank_pipe = 0;
 
 	if (I915_HAS_HOTPLUG(dev)) {
@@ -2506,14 +2503,14 @@ static void i915_irq_uninstall(struct drm_device * dev)
 	}
 
 	I915_WRITE16(HWSTAM, 0xffff);
-	for_each_pipe(pipe)
+	for_each_pipe(pipe) {
+		/* Clear enable bits; then clear status bits */
 		I915_WRITE(PIPESTAT(pipe), 0);
+		I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
+	}
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 
-	for_each_pipe(pipe)
-		I915_WRITE(PIPESTAT(pipe),
-			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
 	I915_WRITE(IIR, I915_READ(IIR));
 }
 
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (7 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:52   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX Chris Wilson
  2012-04-24 21:59 ` [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros Chris Wilson
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

We appear to allow too many pending pageflips as evidenced by an
apparent pin-leak. So borrow the pageflip completion logic from i8xx for
handling PendingFlip in a robust manner.

v2: Address Jesse's reminders about the nuances of gen3 IRQ handling.

References: https://bugzilla.kernel.org/show_bug.cgi?id=41882
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   74 +++++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index e5f627f..1d320e0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2318,16 +2318,31 @@ static void i915_irq_preinstall(struct drm_device * dev)
 static int i915_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 enable_mask;
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
-	/* Unmask the interrupts that we always want on. */
-	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
-
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
 
+	I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
+
+	/* Unmask the interrupts that we always want on. */
+	dev_priv->irq_mask =
+		~(I915_ASLE_INTERRUPT |
+		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+		  I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+		  I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+		  I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+
+	enable_mask =
+		I915_ASLE_INTERRUPT |
+		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+		I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
+		I915_USER_INTERRUPT;
+
 	if (I915_HAS_HOTPLUG(dev)) {
 		/* Enable in IER... */
 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
@@ -2335,12 +2350,6 @@ static int i915_irq_postinstall(struct drm_device *dev)
 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
 	}
 
-	/*
-	 * Enable some error detection, note the instruction error mask
-	 * bit is reserved, so we leave it masked.
-	 */
-	I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
-
 	I915_WRITE(IMR, dev_priv->irq_mask);
 	I915_WRITE(IER, enable_mask);
 	POSTING_READ(IER);
@@ -2380,15 +2389,21 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 	struct drm_i915_master_private *master_priv;
 	u32 iir, new_iir, pipe_stats[I915_MAX_PIPES];
 	unsigned long irqflags;
-	int ret = IRQ_NONE, pipe;
+	u32 flip_mask =
+		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+	u32 flip[2] = {
+		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT,
+		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT
+	};
+	int pipe, ret = IRQ_NONE;
 
 	atomic_inc(&dev_priv->irq_received);
 
 	iir = I915_READ(IIR);
-
-	for (;;) {
+	do {
+		bool irq_received = (iir & ~flip_mask) != 0;
 		bool blc_event = false;
-		int irq_received = iir != 0;
 
 		/* Can't rely on pipestat interrupt bit in iir as it might
 		 * have been cleared after the pipestat interrupt was received.
@@ -2403,15 +2418,13 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 			int reg = PIPESTAT(pipe);
 			pipe_stats[pipe] = I915_READ(reg);
 
-			/*
-			 * Clear the PIPE*STAT regs before the IIR
-			 */
+			/* Clear the PIPE*STAT regs before the IIR */
 			if (pipe_stats[pipe] & 0x8000ffff) {
 				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
 					DRM_DEBUG_DRIVER("pipe %c underrun\n",
 							 pipe_name(pipe));
 				I915_WRITE(reg, pipe_stats[pipe]);
-				irq_received = 1;
+				irq_received = true;
 			}
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -2419,8 +2432,6 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 		if (!irq_received)
 			break;
 
-		ret = IRQ_HANDLED;
-
 		/* Consume port.  Then clear IIR or we'll miss events */
 		if ((I915_HAS_HOTPLUG(dev)) &&
 		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
@@ -2433,26 +2444,26 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 					   &dev_priv->hotplug_work);
 
 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-			I915_READ(PORT_HOTPLUG_STAT);
+			POSTING_READ(PORT_HOTPLUG_STAT);
 		}
 
-		I915_WRITE(IIR, iir);
+		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
 			notify_ring(dev, &dev_priv->ring[RCS]);
 
-		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
-			intel_prepare_page_flip(dev, 0);
-
-		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
-			intel_prepare_page_flip(dev, 1);
-
 		for_each_pipe(pipe) {
+			int plane = pipe;
+			if (IS_MOBILE(dev))
+				plane = !plane;
 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
 			    drm_handle_vblank(dev, pipe)) {
-				i915_pageflip_stall_check(dev, pipe);
-				intel_finish_page_flip(dev, pipe);
+				if (iir & flip[plane]) {
+					intel_prepare_page_flip(dev, plane);
+					intel_finish_page_flip(dev, pipe);
+					flip_mask &= ~flip[plane];
+				}
 			}
 
 			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
@@ -2477,8 +2488,9 @@ static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
 		 * trigger the 99% of 100,000 interrupts test for disabling
 		 * stray interrupts.
 		 */
+		ret = IRQ_HANDLED;
 		iir = new_iir;
-	}
+	} while (iir & ~flip_mask);
 
 	if (dev->primary->master) {
 		master_priv = dev->primary->master->driver_priv;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (8 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:55   ` Jesse Barnes
  2012-04-24 21:59 ` [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros Chris Wilson
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

Since there is only one remaining user of I915_INTERRUPT_ENABLE_FIX,
expand it at the callsite. Quoting Jesse Barnes:

"I'd really like to get rid of these defines at the top of i915_irq.c.
Some are unused and the others just make you check for the right bits
everytime your read the code."

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   38 ++++++++++++++++++--------------------
 1 file changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1d320e0..a1150b7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -39,24 +39,6 @@
 
 #define MAX_NOPID ((u32)~0)
 
-/**
- * Interrupts that are always left unmasked.
- *
- * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
- * we leave them always unmasked in IMR and then control enabling them through
- * PIPESTAT alone.
- */
-#define I915_INTERRUPT_ENABLE_FIX			\
-	(I915_ASLE_INTERRUPT |				\
-	 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |		\
-	 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |		\
-	 I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |	\
-	 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |	\
-	 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
-
-/** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
-
 #define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
 				 PIPE_VBLANK_INTERRUPT_STATUS)
 
@@ -2549,13 +2531,29 @@ static void i965_irq_preinstall(struct drm_device * dev)
 static int i965_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 enable_mask;
 	u32 error_mask;
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
 	/* Unmask the interrupts that we always want on. */
-	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
+	dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
+			       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+			       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+			       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+			       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+			       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+
+	enable_mask = (I915_ASLE_INTERRUPT |
+		       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+		       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+		       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+		       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
+		       I915_USER_INTERRUPT);
+
+	if (IS_G4X(dev))
+		enable_mask |= I915_BSD_USER_INTERRUPT;
 
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros
  2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
                   ` (9 preceding siblings ...)
  2012-04-24 21:59 ` [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX Chris Wilson
@ 2012-04-24 21:59 ` Chris Wilson
  2012-04-25 20:55   ` Jesse Barnes
  10 siblings, 1 reply; 22+ messages in thread
From: Chris Wilson @ 2012-04-24 21:59 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_irq.c |   11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a1150b7..d3500c7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -37,17 +37,6 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
-#define MAX_NOPID ((u32)~0)
-
-#define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
-				 PIPE_VBLANK_INTERRUPT_STATUS)
-
-#define I915_PIPE_VBLANK_ENABLE	(PIPE_START_VBLANK_INTERRUPT_ENABLE |\
-				 PIPE_VBLANK_INTERRUPT_ENABLE)
-
-#define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
-					 DRM_I915_VBLANK_PIPE_B)
-
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3
  2012-04-24 21:59 ` [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3 Chris Wilson
@ 2012-04-25 20:48   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:48 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:45 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> On later gen3, you are able to select the meaning of the FlipPending
> status bit in IIR and change it to FlipDone. This was sometimes done by
> the BIOS leading to confusion on just how pageflipping worked on gen3.
> Simplify the implementation by using the legacy meaning for all gen3
> machines.
> 
> Note: this makes all gen3 machines equally broken...

Looks ok, of course lots of qa on the final result...

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine
  2012-04-24 21:59 ` [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine Chris Wilson
@ 2012-04-25 20:49   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:49 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:46 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> And a couple of miscellaneous cleanups to the main body of the IRQ loop;
> move per-loop condition variables within the scope of the loop and move
> the old DRI1 breadcrumb to the tail of the function and so only execute
> it once.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 irq routine
  2012-04-24 21:59 ` [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 " Chris Wilson
@ 2012-04-25 20:50   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:50 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:47 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> A couple of miscellaneous cleanups as well to move per-loop condition
> variables within the scope of the loop and the update of the DRI1
> breadcrumb to the tail of the function.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3
  2012-04-24 21:59 ` [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3 Chris Wilson
@ 2012-04-25 20:50   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:50 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:48 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_irq.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 878f1c3..a4e074e 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2307,7 +2307,7 @@ static void i915_irq_preinstall(struct drm_device * dev)
>  		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
>  	}
>  
> -	I915_WRITE(HWSTAM, 0xeffe);
> +	I915_WRITE16(HWSTAM, 0xeffe);
>  	for_each_pipe(pipe)
>  		I915_WRITE(PIPESTAT(pipe), 0);
>  	I915_WRITE(IMR, 0xffffffff);
> @@ -2505,7 +2505,7 @@ static void i915_irq_uninstall(struct drm_device * dev)
>  		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
>  	}
>  
> -	I915_WRITE(HWSTAM, 0xffffffff);
> +	I915_WRITE16(HWSTAM, 0xffff);
>  	for_each_pipe(pipe)
>  		I915_WRITE(PIPESTAT(pipe), 0);
>  	I915_WRITE(IMR, 0xffffffff);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall
  2012-04-24 21:59 ` [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall Chris Wilson
@ 2012-04-25 20:51   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:51 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:49 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Bring the for-each-pipe loops together so that the code is easier on the
> eyes.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_irq.c |   11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a4e074e..e5f627f 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2495,9 +2495,6 @@ static void i915_irq_uninstall(struct drm_device * dev)
>  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
>  	int pipe;
>  
> -	if (!dev_priv)
> -		return;
> -
>  	dev_priv->vblank_pipe = 0;
>  
>  	if (I915_HAS_HOTPLUG(dev)) {
> @@ -2506,14 +2503,14 @@ static void i915_irq_uninstall(struct drm_device * dev)
>  	}
>  
>  	I915_WRITE16(HWSTAM, 0xffff);
> -	for_each_pipe(pipe)
> +	for_each_pipe(pipe) {
> +		/* Clear enable bits; then clear status bits */
>  		I915_WRITE(PIPESTAT(pipe), 0);
> +		I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
> +	}
>  	I915_WRITE(IMR, 0xffffffff);
>  	I915_WRITE(IER, 0x0);
>  
> -	for_each_pipe(pipe)
> -		I915_WRITE(PIPESTAT(pipe),
> -			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
>  	I915_WRITE(IIR, I915_READ(IIR));
>  }
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly
  2012-04-24 21:59 ` [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly Chris Wilson
@ 2012-04-25 20:52   ` Jesse Barnes
  0 siblings, 0 replies; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:52 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:50 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> We appear to allow too many pending pageflips as evidenced by an
> apparent pin-leak. So borrow the pageflip completion logic from i8xx for
> handling PendingFlip in a robust manner.
> 
> v2: Address Jesse's reminders about the nuances of gen3 IRQ handling.
> 
> References: https://bugzilla.kernel.org/show_bug.cgi?id=41882
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---

Lots of QA.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX
  2012-04-24 21:59 ` [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX Chris Wilson
@ 2012-04-25 20:55   ` Jesse Barnes
  2012-04-25 21:28     ` Chris Wilson
  0 siblings, 1 reply; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:55 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:51 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Since there is only one remaining user of I915_INTERRUPT_ENABLE_FIX,
> expand it at the callsite. Quoting Jesse Barnes:
> 
> "I'd really like to get rid of these defines at the top of i915_irq.c.
> Some are unused and the others just make you check for the right bits
> everytime your read the code."
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_irq.c |   38 ++++++++++++++++++--------------------
>  1 file changed, 18 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 1d320e0..a1150b7 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -39,24 +39,6 @@
>  
>  #define MAX_NOPID ((u32)~0)
>  
> -/**
> - * Interrupts that are always left unmasked.
> - *
> - * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
> - * we leave them always unmasked in IMR and then control enabling them through
> - * PIPESTAT alone.
> - */
> -#define I915_INTERRUPT_ENABLE_FIX			\
> -	(I915_ASLE_INTERRUPT |				\
> -	 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |		\
> -	 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |		\
> -	 I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |	\
> -	 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |	\
> -	 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
> -
> -/** Interrupts that we mask and unmask at runtime. */
> -#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
> -
>  #define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
>  				 PIPE_VBLANK_INTERRUPT_STATUS)
>  
> @@ -2549,13 +2531,29 @@ static void i965_irq_preinstall(struct drm_device * dev)
>  static int i965_irq_postinstall(struct drm_device *dev)
>  {
>  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> -	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
> +	u32 enable_mask;
>  	u32 error_mask;
>  
>  	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
>  
>  	/* Unmask the interrupts that we always want on. */
> -	dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
> +	dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
> +			       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> +			       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
> +			       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
> +			       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
> +			       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
> +
> +	enable_mask = (I915_ASLE_INTERRUPT |
> +		       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> +		       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
> +		       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
> +		       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
> +		       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
> +		       I915_USER_INTERRUPT);

You could set the enable mask to ~irq_mask | I915_USER_INTERRUPT I
think just to save a little duplication?  No biggie though.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Also this one is a little sneaky because it silently fixes the
BSD_USER_INTERRUPT bug on pre-Cantiga.  But I suppose that's fine...

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros
  2012-04-24 21:59 ` [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros Chris Wilson
@ 2012-04-25 20:55   ` Jesse Barnes
  2012-04-26 20:58     ` Daniel Vetter
  0 siblings, 1 reply; 22+ messages in thread
From: Jesse Barnes @ 2012-04-25 20:55 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Tue, 24 Apr 2012 22:59:52 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_irq.c |   11 -----------
>  1 file changed, 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a1150b7..d3500c7 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -37,17 +37,6 @@
>  #include "i915_trace.h"
>  #include "intel_drv.h"
>  
> -#define MAX_NOPID ((u32)~0)
> -
> -#define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
> -				 PIPE_VBLANK_INTERRUPT_STATUS)
> -
> -#define I915_PIPE_VBLANK_ENABLE	(PIPE_START_VBLANK_INTERRUPT_ENABLE |\
> -				 PIPE_VBLANK_INTERRUPT_ENABLE)
> -
> -#define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
> -					 DRM_I915_VBLANK_PIPE_B)
> -
>  /* For display hotplug interrupt */
>  static void
>  ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)

Yay.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX
  2012-04-25 20:55   ` Jesse Barnes
@ 2012-04-25 21:28     ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2012-04-25 21:28 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, 25 Apr 2012 13:55:12 -0700, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Tue, 24 Apr 2012 22:59:51 +0100
> Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > +	dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
> > +			       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> > +			       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
> > +			       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
> > +			       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
> > +			       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
> > +
> > +	enable_mask = (I915_ASLE_INTERRUPT |
> > +		       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> > +		       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
> > +		       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
> > +		       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
> > +		       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
> > +		       I915_USER_INTERRUPT);
> 
> You could set the enable mask to ~irq_mask | I915_USER_INTERRUPT I
> think just to save a little duplication?  No biggie though.

I considered reducing the duplication, but having just done i8xx/i915
where the relationship between irq_mask and enable_mask was a little
more complicated, I erred on the side of verbosity.

enable_mask = ~dev_priv->irq_mask;
enable_mask |= I915_USER_INTERRUPT;
if (IS_G4X(dev))
  enable_mask |= I915_BSD_USER_INTERRUPT;

Works for me as well.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros
  2012-04-25 20:55   ` Jesse Barnes
@ 2012-04-26 20:58     ` Daniel Vetter
  0 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2012-04-26 20:58 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, Apr 25, 2012 at 01:55:24PM -0700, Jesse Barnes wrote:
> On Tue, 24 Apr 2012 22:59:52 +0100
> Chris Wilson <chris@chris-wilson.co.uk> wrote:
> 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > ---
> >  drivers/gpu/drm/i915/i915_irq.c |   11 -----------
> >  1 file changed, 11 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index a1150b7..d3500c7 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -37,17 +37,6 @@
> >  #include "i915_trace.h"
> >  #include "intel_drv.h"
> >  
> > -#define MAX_NOPID ((u32)~0)
> > -
> > -#define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
> > -				 PIPE_VBLANK_INTERRUPT_STATUS)
> > -
> > -#define I915_PIPE_VBLANK_ENABLE	(PIPE_START_VBLANK_INTERRUPT_ENABLE |\
> > -				 PIPE_VBLANK_INTERRUPT_ENABLE)
> > -
> > -#define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
> > -					 DRM_I915_VBLANK_PIPE_B)
> > -
> >  /* For display hotplug interrupt */
> >  static void
> >  ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
> 
> Yay.
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
I've slurped in the entire series for -next, thanks for the patches and
review.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2012-04-26 20:57 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-24 21:59 [PATCH 01/12] drm/i915: Unconditionally initialise the interrupt workers Chris Wilson
2012-04-24 21:59 ` [PATCH 02/12] drm/i915: Remove redundant initialisation of per-ring IRQ waitqueues Chris Wilson
2012-04-24 21:59 ` [PATCH 03/12] drm/i915: pending_flip_is_done is gen3, name it so Chris Wilson
2012-04-24 21:59 ` [PATCH 04/12] drm/i915: Duplicate and split the gen3/4 irq handler Chris Wilson
2012-04-24 21:59 ` [PATCH 05/12] drm/i915: Clear FlipDone semantics change for pageflipping on gen3 Chris Wilson
2012-04-25 20:48   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 06/12] drm/i915: Remove gen3 irq code from gen4 irq routine Chris Wilson
2012-04-25 20:49   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 07/12] drm/i915: Remove gen4 irq code from gen3 " Chris Wilson
2012-04-25 20:50   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 08/12] drm/i915: HWSTAM is only 16-bit on gen3 Chris Wilson
2012-04-25 20:50   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 09/12] drm/i915: Cleanup gen3 irq uninstall Chris Wilson
2012-04-25 20:51   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 10/12] drm/i915: Handle PendingFlip on gen3 robustly Chris Wilson
2012-04-25 20:52   ` Jesse Barnes
2012-04-24 21:59 ` [PATCH 11/12] drm/i915: Inline I915_INTERRUPT_ENABLE_FIX Chris Wilson
2012-04-25 20:55   ` Jesse Barnes
2012-04-25 21:28     ` Chris Wilson
2012-04-24 21:59 ` [PATCH 12/12] drm/i915: Remove unused and unloved vblank macros Chris Wilson
2012-04-25 20:55   ` Jesse Barnes
2012-04-26 20:58     ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.