I couldn't reproduce this one, but...  Interrupt mask state is lost if
three interrupts occur before the workqueue has run.

Should be straight forward to reproduce even without SMP. I'm pretty
sure Dan Vetter was trying to explain this to me, and I couldn't get it.
My solution I think is different than his though.

Here is a sample failure:
  <pm irq 1<<0 occurs>
  local iir = 1
  spin lock
  mask_pm_irq(1 << 0);
  dev_priv->iir = 1;
  spin_unlock
  clear_pm_irq(1 << 0);

  <pm irq 1 << 1 occurs>
  local iir = 2
  spin lock
  mask_pm_irq(1 << 1); // here is the bug
  dev_priv->iir = 3;
  clear_pm_irq(1 << 1);

  <pm irq 1 << 0 occurs again>
  local iir = 1
  spin lock
  WARN!!!

Cc: Chris Wilson <[email protected]>
Cc: Daniel Vetter <[email protected]>
Signed-off-by: Ben Widawsky <[email protected]>
---
 drivers/gpu/drm/i915/i915_irq.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9cbb0cd..55518e3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -649,8 +649,8 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
                unsigned long flags;
                spin_lock_irqsave(&dev_priv->rps_lock, flags);
                WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-               I915_WRITE(GEN6_PMIMR, pm_iir);
                dev_priv->pm_iir |= pm_iir;
+               I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
                spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
                queue_work(dev_priv->wq, &dev_priv->rps_work);
        }
-- 
1.7.6.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to