[Intel-gfx] [PATCH] i915: Enable IMR passthrough of vblank events before enabling it in pipestat.

Eric Anholt eric at anholt.net
Sat Oct 18 00:48:29 CEST 2008


Otherwise, if we lost the race, the pipestat bit would be set without being
reflected in IIR, and we would never clear the pipestat bit so the pipe
event would never be generated again, and all vblank waits would time out.
---
 drivers/gpu/drm/i915/i915_irq.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3658a04..81b9b22 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -603,6 +603,15 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
 	}
 
 	spin_lock(&dev_priv->user_irq_lock);
+	/* Enabling vblank events in IMR comes before PIPESTAT write, or
+	 * there's a race where the PIPESTAT vblank bit gets set to 1, so
+	 * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
+	 * ISR flashes to 1, but the IIR bit doesn't get set to 1 because
+	 * IMR masks it.  It doesn't ever get set after we clear the masking
+	 * in IMR because the ISR bit is edge, not level-triggered, on the
+	 * OR of PIPESTAT bits.
+	 */
+	i915_enable_irq(dev_priv, interrupt);
 	pipestat = I915_READ(pipestat_reg);
 	if (IS_I965G(dev))
 		pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
@@ -613,7 +622,6 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
 		     PIPE_VBLANK_INTERRUPT_STATUS);
 	I915_WRITE(pipestat_reg, pipestat);
 	(void) I915_READ(pipestat_reg);	/* Posting read */
-	i915_enable_irq(dev_priv, interrupt);
 	spin_unlock(&dev_priv->user_irq_lock);
 
 	return 0;
@@ -644,7 +652,6 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
 	}
 
 	spin_lock(&dev_priv->user_irq_lock);
-	i915_disable_irq(dev_priv, interrupt);
 	pipestat = I915_READ(pipestat_reg);
 	pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
 		      PIPE_VBLANK_INTERRUPT_ENABLE);
@@ -653,6 +660,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
 		     PIPE_VBLANK_INTERRUPT_STATUS);
 	I915_WRITE(pipestat_reg, pipestat);
 	(void) I915_READ(pipestat_reg);	/* Posting read */
+	i915_disable_irq(dev_priv, interrupt);
 	spin_unlock(&dev_priv->user_irq_lock);
 }
 
-- 
1.5.6.5




More information about the Intel-gfx mailing list