drm/i915: extract gt interrupt handler
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 30 Mar 2012 18:24:35 +0000 (20:24 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 9 Apr 2012 16:04:07 +0000 (18:04 +0200)
vlv, ivb and snb all share the gen6+ gt irq handling. 3 copies of the
same stuff is a bit much, so extract it into a little helper.

Now ilk has a different gt irq handling than snb, but shares the same
irq handler (due to the similar display block). So also extract the
ilk gt irq handling to clearly separate these two things.

Nice side effect of this is that we can complete Ben Widawsky's gen6+
irq bit #define cleanup and call the render irq also with the GEN6
alias. Beforehand that code was shared with ilk, and neither option
really made much sense.

As a bonus this enables the error interrupt handling lifted from the
vlv code on snb and ivb, too.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Antagonized-by: Ben Widawsky <ben@bwidawsk.net>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c

index 8496fa55122a39d1654f4e87b68acf85be60a383..6d76ee54278b2eabbb54987c074662d55d0a544c 100644 (file)
@@ -430,6 +430,27 @@ static void gen6_pm_rps_work(struct work_struct *work)
        mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
+static void snb_gt_irq_handler(struct drm_device *dev,
+                              struct drm_i915_private *dev_priv,
+                              u32 gt_iir)
+{
+
+       if (gt_iir & (GEN6_RENDER_USER_INTERRUPT |
+                     GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT))
+               notify_ring(dev, &dev_priv->ring[RCS]);
+       if (gt_iir & GEN6_BSD_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[VCS]);
+       if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[BCS]);
+
+       if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT |
+                     GT_GEN6_BSD_CS_ERROR_INTERRUPT |
+                     GT_RENDER_CS_ERROR_INTERRUPT)) {
+               DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
+               i915_handle_error(dev, false);
+       }
+}
+
 static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -458,19 +479,7 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 
                ret = IRQ_HANDLED;
 
-               if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
-                       notify_ring(dev, &dev_priv->ring[RCS]);
-               if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[VCS]);
-               if (gt_iir & GT_GEN6_BLT_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[BCS]);
-
-               if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT |
-                             GT_GEN6_BSD_CS_ERROR_INTERRUPT |
-                             GT_RENDER_CS_ERROR_INTERRUPT)) {
-                       DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
-                       i915_handle_error(dev, false);
-               }
+               snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                for_each_pipe(pipe) {
@@ -618,12 +627,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
                                READ_BREADCRUMB(dev_priv);
        }
 
-       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
-               notify_ring(dev, &dev_priv->ring[RCS]);
-       if (gt_iir & GEN6_BSD_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[VCS]);
-       if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+       snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
        if (de_iir & DE_GSE_IVB)
                intel_opregion_gse_intr(dev);
@@ -675,6 +679,16 @@ done:
        return ret;
 }
 
+static void ilk_gt_irq_handler(struct drm_device *dev,
+                              struct drm_i915_private *dev_priv,
+                              u32 gt_iir)
+{
+       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
+               notify_ring(dev, &dev_priv->ring[RCS]);
+       if (gt_iir & GT_BSD_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[VCS]);
+}
+
 static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -683,13 +697,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
        u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
        u32 hotplug_mask;
        struct drm_i915_master_private *master_priv;
-       u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
 
        atomic_inc(&dev_priv->irq_received);
 
-       if (IS_GEN6(dev))
-               bsd_usr_interrupt = GEN6_BSD_USER_INTERRUPT;
-
        /* disable master interrupt before clearing iir  */
        de_ier = I915_READ(DEIER);
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
@@ -718,12 +728,10 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
                                READ_BREADCRUMB(dev_priv);
        }
 
-       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
-               notify_ring(dev, &dev_priv->ring[RCS]);
-       if (gt_iir & bsd_usr_interrupt)
-               notify_ring(dev, &dev_priv->ring[VCS]);
-       if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+       if (IS_GEN5(dev))
+               ilk_gt_irq_handler(dev, dev_priv, gt_iir);
+       else
+               snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
        if (de_iir & DE_GSE)
                intel_opregion_gse_intr(dev);