Commit 6005ce42 authored by Daniel Vetter's avatar Daniel Vetter

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: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 4bc9d430
...@@ -2725,7 +2725,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ...@@ -2725,7 +2725,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
/* should always can generate irq */ /* should always can generate irq */
I915_WRITE(DEIIR, I915_READ(DEIIR)); I915_WRITE(DEIIR, I915_READ(DEIIR));
I915_WRITE(DEIMR, dev_priv->irq_mask); I915_WRITE(DEIMR, dev_priv->irq_mask);
I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK); I915_WRITE(DEIER, display_mask |
DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
POSTING_READ(DEIER); POSTING_READ(DEIER);
dev_priv->gt_irq_mask = ~0; dev_priv->gt_irq_mask = ~0;
...@@ -2747,11 +2748,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ...@@ -2747,11 +2748,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
ibx_irq_postinstall(dev); ibx_irq_postinstall(dev);
if (IS_IRONLAKE_M(dev)) { if (IS_IRONLAKE_M(dev)) {
/* Clear & enable PCU event interrupts */ /* Enable PCU event interrupts
I915_WRITE(DEIIR, DE_PCU_EVENT); *
I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT); * spinlocking not required here for correctness since interrupt
/* spinlocking not required here for correctness since interrupt
* setup is guaranteed to run in single-threaded context. But we * setup is guaranteed to run in single-threaded context. But we
* need it to make the assert_spin_locked happy. */ * need it to make the assert_spin_locked happy. */
spin_lock_irqsave(&dev_priv->irq_lock, irqflags); spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment