drm/i915: Simplify interrupt processing for IvyBridge
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 9 May 2012 20:45:44 +0000 (21:45 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 10 May 2012 09:55:23 +0000 (11:55 +0200)
We can take advantage that the PCH_IIR is a subordinate register to
reduce one of the required IIR reads, and that we only need to clear
interrupts handled to reduce the writes. And by simply tidying the code
we can reduce the line count and hopefully make it more readable.

v2: Split out the bugfix from the refactoring.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c

index 14943ba..324431e 100644 (file)
@@ -577,72 +577,61 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       int ret = IRQ_NONE;
-       u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
+       u32 de_iir, gt_iir, de_ier, pm_iir;
+       irqreturn_t ret = IRQ_NONE;
+       int i;
 
        atomic_inc(&dev_priv->irq_received);
 
        /* disable master interrupt before clearing iir  */
        de_ier = I915_READ(DEIER);
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
-       POSTING_READ(DEIER);
 
-       de_iir = I915_READ(DEIIR);
        gt_iir = I915_READ(GTIIR);
-       pch_iir = I915_READ(SDEIIR);
-       pm_iir = I915_READ(GEN6_PMIIR);
-
-       if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && pm_iir == 0)
-               goto done;
-
-       ret = IRQ_HANDLED;
-
-       snb_gt_irq_handler(dev, dev_priv, gt_iir);
-
-       if (de_iir & DE_GSE_IVB)
-               intel_opregion_gse_intr(dev);
-
-       if (de_iir & DE_PLANEA_FLIP_DONE_IVB) {
-               intel_prepare_page_flip(dev, 0);
-               intel_finish_page_flip_plane(dev, 0);
-       }
-
-       if (de_iir & DE_PLANEB_FLIP_DONE_IVB) {
-               intel_prepare_page_flip(dev, 1);
-               intel_finish_page_flip_plane(dev, 1);
+       if (gt_iir) {
+               snb_gt_irq_handler(dev, dev_priv, gt_iir);
+               I915_WRITE(GTIIR, gt_iir);
+               ret = IRQ_HANDLED;
        }
 
-       if (de_iir & DE_PLANEC_FLIP_DONE_IVB) {
-               intel_prepare_page_flip(dev, 2);
-               intel_finish_page_flip_plane(dev, 2);
-       }
+       de_iir = I915_READ(DEIIR);
+       if (de_iir) {
+               if (de_iir & DE_GSE_IVB)
+                       intel_opregion_gse_intr(dev);
+
+               for (i = 0; i < 3; i++) {
+                       if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
+                               intel_prepare_page_flip(dev, i);
+                               intel_finish_page_flip_plane(dev, i);
+                       }
+                       if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+                               drm_handle_vblank(dev, i);
+               }
 
-       if (de_iir & DE_PIPEA_VBLANK_IVB)
-               drm_handle_vblank(dev, 0);
+               /* check event from PCH */
+               if (de_iir & DE_PCH_EVENT_IVB) {
+                       u32 pch_iir = I915_READ(SDEIIR);
 
-       if (de_iir & DE_PIPEB_VBLANK_IVB)
-               drm_handle_vblank(dev, 1);
+                       if (pch_iir & SDE_HOTPLUG_MASK_CPT)
+                               queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+                       pch_irq_handler(dev, pch_iir);
 
-       if (de_iir & DE_PIPEC_VBLANK_IVB)
-               drm_handle_vblank(dev, 2);
+                       /* clear PCH hotplug event before clear CPU irq */
+                       I915_WRITE(SDEIIR, pch_iir);
+               }
 
-       /* check event from PCH */
-       if (de_iir & DE_PCH_EVENT_IVB) {
-               if (pch_iir & SDE_HOTPLUG_MASK_CPT)
-                       queue_work(dev_priv->wq, &dev_priv->hotplug_work);
-               pch_irq_handler(dev, pch_iir);
+               I915_WRITE(DEIIR, de_iir);
+               ret = IRQ_HANDLED;
        }
 
-       if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
-               gen6_queue_rps_work(dev_priv, pm_iir);
-
-       /* should clear PCH hotplug event before clear CPU irq */
-       I915_WRITE(SDEIIR, pch_iir);
-       I915_WRITE(GTIIR, gt_iir);
-       I915_WRITE(DEIIR, de_iir);
-       I915_WRITE(GEN6_PMIIR, pm_iir);
+       pm_iir = I915_READ(GEN6_PMIIR);
+       if (pm_iir) {
+               if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
+                       gen6_queue_rps_work(dev_priv, pm_iir);
+               I915_WRITE(GEN6_PMIIR, pm_iir);
+               ret = IRQ_HANDLED;
+       }
 
-done:
        I915_WRITE(DEIER, de_ier);
        POSTING_READ(DEIER);