summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorEric Anholt2008-10-18 00:41:26 +0200
committerDave Airlie2008-10-23 05:42:27 +0200
commit053d7f244a8739d96d316c77a97cd063804c8e35 (patch)
tree009b443222c13585db343f4ece1a70b0bd28aa42 /drivers/gpu
parentdrm: Remove two leaks of vblank reference count in error paths. (diff)
downloadkernel-qcow2-linux-053d7f244a8739d96d316c77a97cd063804c8e35.tar.gz
kernel-qcow2-linux-053d7f244a8739d96d316c77a97cd063804c8e35.tar.xz
kernel-qcow2-linux-053d7f244a8739d96d316c77a97cd063804c8e35.zip
i915: Enable IMR passthrough of vblank events before enabling it in pipestat.
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. Signed-off-by: Eric Anholt <eric@anholt.net> Acked-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2cd853b2c562..ca55c40353a5 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -605,6 +605,15 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
}
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ /* 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;
@@ -615,7 +624,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_irqrestore(&dev_priv->user_irq_lock, irqflags);
return 0;