drm/i915: add ILK/SNB support to ivybridge_irq_handler
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Fri, 12 Jul 2013 22:56:30 +0000 (19:56 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 19 Jul 2013 16:08:55 +0000 (18:08 +0200)
And then rename it to ironlake_irq_handler. Also move
ilk_gt_irq_handler up to avoid forward declarations.

In the previous patches I did small modifications to both
ironlake_irq_handler an ivybridge_irq_handler so they became very
similar functions. Now it should be very easy to verify that all we
need to add ILK/SNB support is to call ilk_gt_irq_handler, call
ilk_display_irq_handler and avoid reading pm_iir on gen 5.

v2: - Rebase due to changes on the previous patches
    - Move pm_iir to a tighter scope (Chris)
    - Change some Gen checks for readability

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c

index 597a3d5ae7e155d7b3392ed7d39c43740284dfa9..7c201f7906eb4a97aadafde8b88214c17c713b9b 100644 (file)
@@ -844,6 +844,17 @@ static void ivybridge_parity_error_irq_handler(struct drm_device *dev)
        queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
 }
 
+static void ilk_gt_irq_handler(struct drm_device *dev,
+                              struct drm_i915_private *dev_priv,
+                              u32 gt_iir)
+{
+       if (gt_iir &
+           (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
+               notify_ring(dev, &dev_priv->ring[RCS]);
+       if (gt_iir & ILK_BSD_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[VCS]);
+}
+
 static void snb_gt_irq_handler(struct drm_device *dev,
                               struct drm_i915_private *dev_priv,
                               u32 gt_iir)
@@ -1285,11 +1296,11 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
        }
 }
 
-static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
+static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier = 0;
+       u32 de_iir, gt_iir, de_ier, sde_ier = 0;
        irqreturn_t ret = IRQ_NONE;
 
        atomic_inc(&dev_priv->irq_received);
@@ -1329,27 +1340,34 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 
        gt_iir = I915_READ(GTIIR);
        if (gt_iir) {
-               snb_gt_irq_handler(dev, dev_priv, gt_iir);
+               if (IS_GEN5(dev))
+                       ilk_gt_irq_handler(dev, dev_priv, gt_iir);
+               else
+                       snb_gt_irq_handler(dev, dev_priv, gt_iir);
                I915_WRITE(GTIIR, gt_iir);
                ret = IRQ_HANDLED;
        }
 
        de_iir = I915_READ(DEIIR);
        if (de_iir) {
-               ivb_display_irq_handler(dev, de_iir);
-
+               if (INTEL_INFO(dev)->gen >= 7)
+                       ivb_display_irq_handler(dev, de_iir);
+               else
+                       ilk_display_irq_handler(dev, de_iir);
                I915_WRITE(DEIIR, de_iir);
                ret = IRQ_HANDLED;
        }
 
-       pm_iir = I915_READ(GEN6_PMIIR);
-       if (pm_iir) {
-               if (IS_HASWELL(dev))
-                       hsw_pm_irq_handler(dev_priv, pm_iir);
-               else if (pm_iir & GEN6_PM_RPS_EVENTS)
-                       gen6_rps_irq_handler(dev_priv, pm_iir);
-               I915_WRITE(GEN6_PMIIR, pm_iir);
-               ret = IRQ_HANDLED;
+       if (INTEL_INFO(dev)->gen >= 6) {
+               u32 pm_iir = I915_READ(GEN6_PMIIR);
+               if (pm_iir) {
+                       if (IS_HASWELL(dev))
+                               hsw_pm_irq_handler(dev_priv, pm_iir);
+                       else if (pm_iir & GEN6_PM_RPS_EVENTS)
+                               gen6_rps_irq_handler(dev_priv, pm_iir);
+                       I915_WRITE(GEN6_PMIIR, pm_iir);
+                       ret = IRQ_HANDLED;
+               }
        }
 
        if (IS_HASWELL(dev)) {
@@ -1369,75 +1387,6 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
        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_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-               notify_ring(dev, &dev_priv->ring[RCS]);
-       if (gt_iir & ILK_BSD_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[VCS]);
-}
-
-static irqreturn_t ironlake_irq_handler(int irq, void *arg)
-{
-       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, sde_ier;
-
-       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);
-
-       /* Disable south interrupts. We'll only write to SDEIIR once, so further
-        * interrupts will will be stored on its back queue, and then we'll be
-        * able to process them after we restore SDEIER (as soon as we restore
-        * it, we'll get an interrupt if SDEIIR still has something to process
-        * due to its back queue). */
-       sde_ier = I915_READ(SDEIER);
-       I915_WRITE(SDEIER, 0);
-       POSTING_READ(SDEIER);
-
-       gt_iir = I915_READ(GTIIR);
-       if (gt_iir) {
-               if (IS_GEN5(dev))
-                       ilk_gt_irq_handler(dev, dev_priv, gt_iir);
-               else
-                       snb_gt_irq_handler(dev, dev_priv, gt_iir);
-               I915_WRITE(GTIIR, gt_iir);
-               ret = IRQ_HANDLED;
-       }
-
-       de_iir = I915_READ(DEIIR);
-       if (de_iir) {
-               ilk_display_irq_handler(dev, de_iir);
-               I915_WRITE(DEIIR, de_iir);
-               ret = IRQ_HANDLED;
-       }
-
-       if (IS_GEN6(dev)) {
-               u32 pm_iir = I915_READ(GEN6_PMIIR);
-               if (pm_iir) {
-                       if (pm_iir & GEN6_PM_RPS_EVENTS)
-                               gen6_rps_irq_handler(dev_priv, pm_iir);
-                       I915_WRITE(GEN6_PMIIR, pm_iir);
-                       ret = IRQ_HANDLED;
-               }
-       }
-
-       I915_WRITE(DEIER, de_ier);
-       POSTING_READ(DEIER);
-       I915_WRITE(SDEIER, sde_ier);
-       POSTING_READ(SDEIER);
-
-       return ret;
-}
-
 /**
  * i915_error_work_func - do process context error handling work
  * @work: work struct
@@ -3118,7 +3067,7 @@ void intel_irq_init(struct drm_device *dev)
                dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
        } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
                /* Share uninstall handlers with ILK/SNB */
-               dev->driver->irq_handler = ivybridge_irq_handler;
+               dev->driver->irq_handler = ironlake_irq_handler;
                dev->driver->irq_preinstall = ironlake_irq_preinstall;
                dev->driver->irq_postinstall = ivybridge_irq_postinstall;
                dev->driver->irq_uninstall = ironlake_irq_uninstall;