| From 0ca8a9ab5a237f848ff1b83e6acc51fa4a24baa6 Mon Sep 17 00:00:00 2001 |
| From: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Date: Thu, 27 Jun 2013 13:44:59 +0200 |
| Subject: 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> |
| (cherry picked from commit 6005ce42433df3f69de99d7e730383a6adb852ef) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_irq.c | 11 +++++------ |
| 1 file changed, 5 insertions(+), 6 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c |
| index ecea1896b0cc..27374f421354 100644 |
| --- a/drivers/gpu/drm/i915/i915_irq.c |
| +++ b/drivers/gpu/drm/i915/i915_irq.c |
| @@ -2771,7 +2771,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) |
| /* should always can generate irq */ |
| I915_WRITE(DEIIR, I915_READ(DEIIR)); |
| 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); |
| |
| dev_priv->gt_irq_mask = ~0; |
| @@ -2793,11 +2794,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) |
| ibx_irq_postinstall(dev); |
| |
| if (IS_IRONLAKE_M(dev)) { |
| - /* Clear & 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 |
| + /* Enable PCU event interrupts |
| + * |
| + * spinlocking not required here for correctness since interrupt |
| * setup is guaranteed to run in single-threaded context. But we |
| * need it to make the assert_spin_locked happy. */ |
| spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| -- |
| 1.8.5.rc3 |
| |