aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-06-27 07:44:59 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-01 05:14:55 -0400
commit6005ce42433df3f69de99d7e730383a6adb852ef (patch)
tree6e57d18f44d5a929c76013d0c62aa9c8253843e9 /drivers/gpu/drm/i915/i915_irq.c
parent4bc9d4301573403c578e545b34dceac61891f39c (diff)
drm/i915: close tiny race in the ilk pcu even interrupt setup
By the time we write DEIER in the postinstall hook the interrupt handler could run any time. And it does modify DEIER to handle interrupts. Hence the DEIER read-modify-write cycle for enabling the PCU event source is racy. Close this races the same way we handle vblank interrupts: Unconditionally enable the interrupt in the IER register, but conditionally mask it in IMR. The later poses no such race since the interrupt handler does not touch DEIMR. Also update the comment, the clearing has already happened unconditionally above. v2: Actually shove the updated comment into the right train^W commit, as spotted by Paulo. Cc: Paulo Zanoni <przanoni@gmail.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 61cd87999df3..bff9abda81c6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2725,7 +2725,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
2725 /* should always can generate irq */ 2725 /* should always can generate irq */
2726 I915_WRITE(DEIIR, I915_READ(DEIIR)); 2726 I915_WRITE(DEIIR, I915_READ(DEIIR));
2727 I915_WRITE(DEIMR, dev_priv->irq_mask); 2727 I915_WRITE(DEIMR, dev_priv->irq_mask);
2728 I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK); 2728 I915_WRITE(DEIER, display_mask |
2729 DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
2729 POSTING_READ(DEIER); 2730 POSTING_READ(DEIER);
2730 2731
2731 dev_priv->gt_irq_mask = ~0; 2732 dev_priv->gt_irq_mask = ~0;
@@ -2747,11 +2748,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
2747 ibx_irq_postinstall(dev); 2748 ibx_irq_postinstall(dev);
2748 2749
2749 if (IS_IRONLAKE_M(dev)) { 2750 if (IS_IRONLAKE_M(dev)) {
2750 /* Clear & enable PCU event interrupts */ 2751 /* Enable PCU event interrupts
2751 I915_WRITE(DEIIR, DE_PCU_EVENT); 2752 *
2752 I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT); 2753 * spinlocking not required here for correctness since interrupt
2753
2754 /* spinlocking not required here for correctness since interrupt
2755 * setup is guaranteed to run in single-threaded context. But we 2754 * setup is guaranteed to run in single-threaded context. But we
2756 * need it to make the assert_spin_locked happy. */ 2755 * need it to make the assert_spin_locked happy. */
2757 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2756 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);