diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 10 |
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) | |||
605 | } | 605 | } |
606 | 606 | ||
607 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 607 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
608 | /* Enabling vblank events in IMR comes before PIPESTAT write, or | ||
609 | * there's a race where the PIPESTAT vblank bit gets set to 1, so | ||
610 | * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in | ||
611 | * ISR flashes to 1, but the IIR bit doesn't get set to 1 because | ||
612 | * IMR masks it. It doesn't ever get set after we clear the masking | ||
613 | * in IMR because the ISR bit is edge, not level-triggered, on the | ||
614 | * OR of PIPESTAT bits. | ||
615 | */ | ||
616 | i915_enable_irq(dev_priv, interrupt); | ||
608 | pipestat = I915_READ(pipestat_reg); | 617 | pipestat = I915_READ(pipestat_reg); |
609 | if (IS_I965G(dev)) | 618 | if (IS_I965G(dev)) |
610 | pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE; | 619 | pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE; |
@@ -615,7 +624,6 @@ int i915_enable_vblank(struct drm_device *dev, int plane) | |||
615 | PIPE_VBLANK_INTERRUPT_STATUS); | 624 | PIPE_VBLANK_INTERRUPT_STATUS); |
616 | I915_WRITE(pipestat_reg, pipestat); | 625 | I915_WRITE(pipestat_reg, pipestat); |
617 | (void) I915_READ(pipestat_reg); /* Posting read */ | 626 | (void) I915_READ(pipestat_reg); /* Posting read */ |
618 | i915_enable_irq(dev_priv, interrupt); | ||
619 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); | 627 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); |
620 | 628 | ||
621 | return 0; | 629 | return 0; |