From: Ville Syrjälä <ville.syrj...@linux.intel.com>

All the older platforms already follow the ack+handler apporoach
for interrupts. Convert ilk+ as well. As the number of registers
involved is rather large we'll introduce a few more structs to
carry the register values around.

Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 445 +++++++++++++++++++++-----------
 1 file changed, 295 insertions(+), 150 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 14e0e9fe1853..6a437c7170b9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2276,6 +2276,13 @@ static irqreturn_t cherryview_irq_handler(int irq, void 
*arg)
        return ret;
 }
 
+struct ilk_de_irq_regs {
+       u32 iir;
+       u32 err_int; /* ivb/hsw */
+       u32 psr_iir; /* hsw */
+       struct hpd_irq_regs hpd;
+};
+
 struct pch_irq_regs {
        u32 iir;
        u32 serr_int; /* cpt/lpt */
@@ -2382,9 +2389,17 @@ static void ibx_irq_handler(struct drm_i915_private 
*dev_priv,
                intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
 }
 
-static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
+static void ivb_err_int_ack(struct drm_i915_private *dev_priv,
+                           struct ilk_de_irq_regs *de)
 {
-       u32 err_int = I915_READ(GEN7_ERR_INT);
+       de->err_int = I915_READ(GEN7_ERR_INT);
+       I915_WRITE(GEN7_ERR_INT, de->err_int);
+}
+
+static void ivb_err_int_handler(struct drm_i915_private *dev_priv,
+                               const struct ilk_de_irq_regs *de)
+{
+       u32 err_int = de->err_int;
        enum pipe pipe;
 
        if (err_int & ERR_INT_POISON)
@@ -2401,8 +2416,6 @@ static void ivb_err_int_handler(struct drm_i915_private 
*dev_priv)
                                hsw_pipe_crc_irq_handler(dev_priv, pipe);
                }
        }
-
-       I915_WRITE(GEN7_ERR_INT, err_int);
 }
 
 static void cpt_serr_int_ack(struct drm_i915_private *dev_priv,
@@ -2579,17 +2592,38 @@ static void ilk_hpd_irq_handler(struct drm_i915_private 
*dev_priv,
        intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
 }
 
+static void ilk_display_irq_ack(struct drm_i915_private *dev_priv,
+                               struct ilk_de_irq_regs *de,
+                               struct pch_irq_regs *pch)
+{
+       de->hpd.hotplug_trigger = de->iir & DE_DP_A_HOTPLUG;
+
+       if (de->hpd.hotplug_trigger)
+               ilk_hpd_irq_ack(dev_priv, &de->hpd);
+
+       /* check event from PCH */
+       if (de->iir & DE_PCH_EVENT) {
+               pch->iir = I915_READ(SDEIIR);
+
+               if (HAS_PCH_CPT(dev_priv))
+                       cpt_irq_ack(dev_priv, pch);
+               else
+                       ibx_irq_ack(dev_priv, pch);
+
+               /* should clear PCH hotplug event before clear CPU irq */
+               I915_WRITE(SDEIIR, pch->iir);
+       }
+}
+
 static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
-                                   u32 de_iir)
+                                   const struct ilk_de_irq_regs *de,
+                                   const struct pch_irq_regs *pch)
 {
-       struct hpd_irq_regs hpd = {};
+       u32 de_iir = de->iir;
        enum pipe pipe;
 
-       hpd.hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
-       if (hpd.hotplug_trigger) {
-               ilk_hpd_irq_ack(dev_priv, &hpd);
-               ilk_hpd_irq_handler(dev_priv, &hpd, hpd_ilk);
-       }
+       if (de->hpd.hotplug_trigger)
+               ilk_hpd_irq_handler(dev_priv, &de->hpd, hpd_ilk);
 
        if (de_iir & DE_AUX_CHANNEL_A)
                dp_aux_irq_handler(dev_priv);
@@ -2613,47 +2647,65 @@ static void ilk_display_irq_handler(struct 
drm_i915_private *dev_priv,
 
        /* check event from PCH */
        if (de_iir & DE_PCH_EVENT) {
-               struct pch_irq_regs pch = {};
-
-               pch.iir = I915_READ(SDEIIR);
-
-               if (HAS_PCH_CPT(dev_priv)) {
-                       cpt_irq_ack(dev_priv, &pch);
-                       cpt_irq_handler(dev_priv, &pch);
-               } else {
-                       ibx_irq_ack(dev_priv, &pch);
-                       ibx_irq_handler(dev_priv, &pch);
-               }
-
-               /* should clear PCH hotplug event before clear CPU irq */
-               I915_WRITE(SDEIIR, pch.iir);
+               if (HAS_PCH_CPT(dev_priv))
+                       cpt_irq_handler(dev_priv, pch);
+               else
+                       ibx_irq_handler(dev_priv, pch);
        }
 
        if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT)
                ironlake_rps_change_irq_handler(dev_priv);
 }
 
+static void hsw_psr_irq_ack(struct drm_i915_private *dev_priv,
+                           u32 *psr_iir)
+{
+       *psr_iir = I915_READ(EDP_PSR_IIR);
+       if (*psr_iir)
+               I915_WRITE(EDP_PSR_IIR, *psr_iir);
+}
+
+static void ivb_display_irq_ack(struct drm_i915_private *dev_priv,
+                               struct ilk_de_irq_regs *de,
+                               struct pch_irq_regs *pch)
+{
+       de->hpd.hotplug_trigger = de->iir & DE_DP_A_HOTPLUG_IVB;
+
+       if (de->hpd.hotplug_trigger)
+               ilk_hpd_irq_ack(dev_priv, &de->hpd);
+
+       if (de->iir & DE_ERR_INT_IVB)
+               ivb_err_int_ack(dev_priv, de);
+
+       if (de->iir & DE_EDP_PSR_INT_HSW)
+               hsw_psr_irq_ack(dev_priv, &de->psr_iir);
+
+       /* check event from PCH */
+       if (!HAS_PCH_NOP(dev_priv) && de->iir & DE_PCH_EVENT_IVB) {
+               pch->iir = I915_READ(SDEIIR);
+
+               cpt_irq_ack(dev_priv, pch);
+
+               /* clear PCH hotplug event before clear CPU irq */
+               I915_WRITE(SDEIIR, pch->iir);
+       }
+}
+
 static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
-                                   u32 de_iir)
+                                   const struct ilk_de_irq_regs *de,
+                                   const struct pch_irq_regs *pch)
 {
-       struct hpd_irq_regs hpd = {};
+       u32 de_iir = de->iir;
        enum pipe pipe;
 
-       hpd.hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
-       if (hpd.hotplug_trigger)  {
-               ilk_hpd_irq_ack(dev_priv, &hpd);
-               ilk_hpd_irq_handler(dev_priv, &hpd, hpd_ivb);
-       }
+       if (de->hpd.hotplug_trigger)
+               ilk_hpd_irq_handler(dev_priv, &de->hpd, hpd_ivb);
 
        if (de_iir & DE_ERR_INT_IVB)
-               ivb_err_int_handler(dev_priv);
+               ivb_err_int_handler(dev_priv, de);
 
-       if (de_iir & DE_EDP_PSR_INT_HSW) {
-               u32 psr_iir = I915_READ(EDP_PSR_IIR);
-
-               intel_psr_irq_handler(dev_priv, psr_iir);
-               I915_WRITE(EDP_PSR_IIR, psr_iir);
-       }
+       if (de_iir & DE_EDP_PSR_INT_HSW)
+               intel_psr_irq_handler(dev_priv, de->psr_iir);
 
        if (de_iir & DE_AUX_CHANNEL_A_IVB)
                dp_aux_irq_handler(dev_priv);
@@ -2662,22 +2714,13 @@ static void ivb_display_irq_handler(struct 
drm_i915_private *dev_priv,
                intel_opregion_asle_intr(dev_priv);
 
        for_each_pipe(dev_priv, pipe) {
-               if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
+               if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
                        drm_handle_vblank(&dev_priv->drm, pipe);
        }
 
        /* check event from PCH */
-       if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
-               struct pch_irq_regs pch = {};
-
-               pch.iir = I915_READ(SDEIIR);
-
-               cpt_irq_ack(dev_priv, &pch);
-               cpt_irq_handler(dev_priv, &pch);
-
-               /* clear PCH hotplug event before clear CPU irq */
-               I915_WRITE(SDEIIR, pch.iir);
-       }
+       if (!HAS_PCH_NOP(dev_priv) && de_iir & DE_PCH_EVENT_IVB)
+               cpt_irq_handler(dev_priv, pch);
 }
 
 /*
@@ -2692,7 +2735,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void 
*arg)
 {
        struct drm_device *dev = arg;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       u32 de_iir, gt_iir, de_ier, sde_ier = 0;
+       u32 gt_iir, pm_iir = 0, de_ier, sde_ier = 0;
+       struct ilk_de_irq_regs de = {};
+       struct pch_irq_regs pch = {};
        irqreturn_t ret = IRQ_NONE;
 
        if (!intel_irqs_enabled(dev_priv))
@@ -2718,38 +2763,50 @@ static irqreturn_t ironlake_irq_handler(int irq, void 
*arg)
        /* Find, clear, then process each source of interrupt */
 
        gt_iir = I915_READ(GTIIR);
-       if (gt_iir) {
+       de.iir = I915_READ(DEIIR);
+       if (INTEL_GEN(dev_priv) >= 6)
+               pm_iir = I915_READ(GEN6_PMIIR);
+
+       if (gt_iir)
                I915_WRITE(GTIIR, gt_iir);
-               ret = IRQ_HANDLED;
-               if (INTEL_GEN(dev_priv) >= 6)
-                       snb_gt_irq_handler(dev_priv, gt_iir);
-               else
-                       ilk_gt_irq_handler(dev_priv, gt_iir);
-       }
 
-       de_iir = I915_READ(DEIIR);
-       if (de_iir) {
-               I915_WRITE(DEIIR, de_iir);
-               ret = IRQ_HANDLED;
+       if (de.iir) {
                if (INTEL_GEN(dev_priv) >= 7)
-                       ivb_display_irq_handler(dev_priv, de_iir);
+                       ivb_display_irq_ack(dev_priv, &de, &pch);
                else
-                       ilk_display_irq_handler(dev_priv, de_iir);
-       }
+                       ilk_display_irq_ack(dev_priv, &de, &pch);
 
-       if (INTEL_GEN(dev_priv) >= 6) {
-               u32 pm_iir = I915_READ(GEN6_PMIIR);
-               if (pm_iir) {
-                       I915_WRITE(GEN6_PMIIR, pm_iir);
-                       ret = IRQ_HANDLED;
-                       gen6_rps_irq_handler(dev_priv, pm_iir);
-               }
+               I915_WRITE(DEIIR, de.iir);
        }
 
+       if (pm_iir)
+               I915_WRITE(GEN6_PMIIR, pm_iir);
+
        I915_WRITE(DEIER, de_ier);
        if (!HAS_PCH_NOP(dev_priv))
                I915_WRITE(SDEIER, sde_ier);
 
+       if (gt_iir) {
+               ret = IRQ_HANDLED;
+               if (INTEL_GEN(dev_priv) >= 6)
+                       snb_gt_irq_handler(dev_priv, gt_iir);
+               else
+                       ilk_gt_irq_handler(dev_priv, gt_iir);
+       }
+
+       if (de.iir) {
+               ret = IRQ_HANDLED;
+               if (INTEL_GEN(dev_priv) >= 7)
+                       ivb_display_irq_handler(dev_priv, &de, &pch);
+               else
+                       ilk_display_irq_handler(dev_priv, &de, &pch);
+       }
+
+       if (pm_iir) {
+               ret = IRQ_HANDLED;
+               gen6_rps_irq_handler(dev_priv, pm_iir);
+       }
+
        /* IRQs are synced during runtime_suspend, we don't require a wakeref */
        enable_rpm_wakeref_asserts(dev_priv);
 
@@ -2776,37 +2833,129 @@ static void bxt_hpd_irq_handler(struct 
drm_i915_private *dev_priv,
        intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
 }
 
-static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+struct gen8_de_irq_regs {
+       u32 pipe_iir[I915_MAX_PIPES];
+       u32 port_iir;
+       u32 misc_iir;
+       u32 psr_iir;
+       u32 hpd_iir; /* icl+ */
+       struct hpd_irq_regs ddi;
+       struct hpd_irq_regs tc, tbt; /* icl+ */
+};
+
+static void gen11_hpd_irq_ack(struct drm_i915_private *dev_priv,
+                             struct gen8_de_irq_regs *de)
+{
+       de->tc.hotplug_trigger = de->hpd_iir & GEN11_DE_TC_HOTPLUG_MASK;
+       de->tbt.hotplug_trigger = de->hpd_iir & GEN11_DE_TBT_HOTPLUG_MASK;
+
+       if (de->tc.hotplug_trigger) {
+               de->tc.dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL);
+               I915_WRITE(GEN11_TC_HOTPLUG_CTL, de->tc.dig_hotplug_reg);
+       }
+
+       if (de->tbt.hotplug_trigger) {
+               de->tbt.dig_hotplug_reg = I915_READ(GEN11_TBT_HOTPLUG_CTL);
+               I915_WRITE(GEN11_TBT_HOTPLUG_CTL, de->tbt.dig_hotplug_reg);
+       }
+}
+
+static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv,
+                                 const struct gen8_de_irq_regs *de)
 {
-       struct hpd_irq_regs tc = {};
-       struct hpd_irq_regs tbt = {};
        u32 pin_mask = 0, long_mask = 0;
 
-       tc.hotplug_trigger = iir & GEN11_DE_TC_HOTPLUG_MASK;
-       tbt.hotplug_trigger = iir & GEN11_DE_TBT_HOTPLUG_MASK;
-
-       if (tc.hotplug_trigger) {
-               tc.dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL);
-               I915_WRITE(GEN11_TC_HOTPLUG_CTL, tc.dig_hotplug_reg);
-
+       if (de->tc.hotplug_trigger) {
                intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
-                                  &tc, hpd_gen11,
+                                  &de->tc, hpd_gen11,
                                   gen11_port_hotplug_long_detect);
        }
 
-       if (tbt.hotplug_trigger) {
-               tbt.dig_hotplug_reg = I915_READ(GEN11_TBT_HOTPLUG_CTL);
-               I915_WRITE(GEN11_TBT_HOTPLUG_CTL, tbt.dig_hotplug_reg);
-
+       if (de->tbt.hotplug_trigger) {
                intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
-                                  &tbt, hpd_gen11,
+                                  &de->tbt, hpd_gen11,
                                   gen11_port_hotplug_long_detect);
        }
 
        if (pin_mask)
                intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
        else
-               DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", iir);
+               DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", de->hpd_iir);
+}
+
+static void
+gen8_de_irq_ack(struct drm_i915_private *dev_priv, u32 master_ctl,
+               struct gen8_de_irq_regs *de, struct pch_irq_regs *pch)
+{
+       enum pipe pipe;
+
+       if (master_ctl & GEN8_DE_MISC_IRQ) {
+               de->misc_iir = I915_READ(GEN8_DE_MISC_IIR);
+
+               if (de->misc_iir) {
+                       if (de->misc_iir & GEN8_DE_EDP_PSR)
+                               hsw_psr_irq_ack(dev_priv, &de->psr_iir);
+
+                       I915_WRITE(GEN8_DE_MISC_IIR, de->misc_iir);
+               }
+       }
+
+       if (INTEL_GEN(dev_priv) >= 11 && master_ctl & GEN11_DE_HPD_IRQ) {
+               de->hpd_iir = I915_READ(GEN11_DE_HPD_IIR);
+
+               if (de->hpd_iir) {
+                       gen11_hpd_irq_ack(dev_priv, de);
+
+                       I915_WRITE(GEN11_DE_HPD_IIR, de->hpd_iir);
+               }
+       }
+
+       if (master_ctl & GEN8_DE_PORT_IRQ) {
+               de->port_iir = I915_READ(GEN8_DE_PORT_IIR);
+
+               if (de->port_iir) {
+                       if (IS_GEN9_LP(dev_priv)) {
+                               de->ddi.hotplug_trigger = de->port_iir & 
BXT_DE_PORT_HOTPLUG_MASK;
+                               if (de->ddi.hotplug_trigger)
+                                       bxt_hpd_irq_ack(dev_priv, &de->ddi);
+                       } else if (IS_BROADWELL(dev_priv)) {
+                               de->ddi.hotplug_trigger = de->port_iir & 
GEN8_PORT_DP_A_HOTPLUG;
+                               if (de->ddi.hotplug_trigger)
+                                       ilk_hpd_irq_ack(dev_priv, &de->ddi);
+                       }
+
+                       I915_WRITE(GEN8_DE_PORT_IIR, de->port_iir);
+               }
+       }
+
+       for_each_pipe(dev_priv, pipe) {
+               if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
+                       continue;
+
+               de->pipe_iir[pipe] = I915_READ(GEN8_DE_PIPE_IIR(pipe));
+               if (de->pipe_iir[pipe])
+                       I915_WRITE(GEN8_DE_PIPE_IIR(pipe), de->pipe_iir[pipe]);
+       }
+
+       if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
+           master_ctl & GEN8_DE_PCH_IRQ) {
+               /*
+                * FIXME(BDW): Assume for now that the new interrupt handling
+                * scheme also closed the SDE interrupt handling race we've seen
+                * on older pch-split platforms. But this needs testing.
+                */
+               pch->iir = I915_READ(SDEIIR);
+               if (pch->iir) {
+                       if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+                               icp_irq_ack(dev_priv, pch);
+                       if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
+                               spt_irq_ack(dev_priv, pch);
+                       else
+                               cpt_irq_ack(dev_priv, pch);
+
+                       I915_WRITE(SDEIIR, pch->iir);
+               }
+       }
 }
 
 static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
@@ -2837,57 +2986,51 @@ static u32 gen8_de_pipe_fault_mask(struct 
drm_i915_private *dev_priv)
 }
 
 static irqreturn_t
-gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
+gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl,
+                   const struct gen8_de_irq_regs *de,
+                   const struct pch_irq_regs *pch)
 {
        irqreturn_t ret = IRQ_NONE;
-       u32 iir;
        enum pipe pipe;
 
        if (master_ctl & GEN8_DE_MISC_IRQ) {
-               iir = I915_READ(GEN8_DE_MISC_IIR);
+               u32 iir = de->misc_iir;
+
                if (iir) {
                        bool found = false;
 
-                       I915_WRITE(GEN8_DE_MISC_IIR, iir);
-                       ret = IRQ_HANDLED;
-
                        if (iir & GEN8_DE_MISC_GSE) {
                                intel_opregion_asle_intr(dev_priv);
                                found = true;
                        }
 
                        if (iir & GEN8_DE_EDP_PSR) {
-                               u32 psr_iir = I915_READ(EDP_PSR_IIR);
-
-                               intel_psr_irq_handler(dev_priv, psr_iir);
-                               I915_WRITE(EDP_PSR_IIR, psr_iir);
+                               intel_psr_irq_handler(dev_priv, de->psr_iir);
                                found = true;
                        }
 
                        if (!found)
                                DRM_ERROR("Unexpected DE Misc interrupt\n");
-               }
-               else
+               } else {
                        DRM_ERROR("The master control interrupt lied (DE 
MISC)!\n");
+               }
        }
 
        if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
-               iir = I915_READ(GEN11_DE_HPD_IIR);
-               if (iir) {
-                       I915_WRITE(GEN11_DE_HPD_IIR, iir);
-                       ret = IRQ_HANDLED;
-                       gen11_hpd_irq_handler(dev_priv, iir);
-               } else {
+               u32 iir = de->hpd_iir;
+
+               if (iir)
+                       gen11_hpd_irq_handler(dev_priv, de);
+               else
                        DRM_ERROR("The master control interrupt lied, (DE 
HPD)!\n");
-               }
        }
 
        if (master_ctl & GEN8_DE_PORT_IRQ) {
-               iir = I915_READ(GEN8_DE_PORT_IIR);
+               u32 iir = de->port_iir;
+
                if (iir) {
                        bool found = false;
 
-                       I915_WRITE(GEN8_DE_PORT_IIR, iir);
                        ret = IRQ_HANDLED;
 
                        if (iir & gen8_de_port_aux_mask(dev_priv)) {
@@ -2895,24 +3038,12 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, 
u32 master_ctl)
                                found = true;
                        }
 
-                       if (IS_GEN9_LP(dev_priv)) {
-                               struct hpd_irq_regs ddi = {};
-
-                               ddi.hotplug_trigger = iir & 
BXT_DE_PORT_HOTPLUG_MASK;
-                               if (ddi.hotplug_trigger) {
-                                       bxt_hpd_irq_ack(dev_priv, &ddi);
-                                       bxt_hpd_irq_handler(dev_priv, &ddi, 
hpd_bxt);
-                                       found = true;
-                               }
-                       } else if (IS_BROADWELL(dev_priv)) {
-                               struct hpd_irq_regs ddi = {};
-
-                               ddi.hotplug_trigger = iir & 
GEN8_PORT_DP_A_HOTPLUG;
-                               if (ddi.hotplug_trigger) {
-                                       ilk_hpd_irq_ack(dev_priv, &ddi);
-                                       ilk_hpd_irq_handler(dev_priv, &ddi, 
hpd_bdw);
-                                       found = true;
-                               }
+                       if (IS_GEN9_LP(dev_priv) && de->ddi.hotplug_trigger) {
+                               bxt_hpd_irq_handler(dev_priv, &de->ddi, 
hpd_bxt);
+                               found = true;
+                       } else if (IS_BROADWELL(dev_priv) && 
de->ddi.hotplug_trigger) {
+                               ilk_hpd_irq_handler(dev_priv, &de->ddi, 
hpd_bdw);
+                               found = true;
                        }
 
                        if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) {
@@ -2922,25 +3053,24 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, 
u32 master_ctl)
 
                        if (!found)
                                DRM_ERROR("Unexpected DE Port interrupt\n");
-               }
-               else
+               } else {
                        DRM_ERROR("The master control interrupt lied (DE 
PORT)!\n");
+               }
        }
 
        for_each_pipe(dev_priv, pipe) {
+               u32 iir = de->pipe_iir[pipe];
                u32 fault_errors;
 
                if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
                        continue;
 
-               iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
                if (!iir) {
                        DRM_ERROR("The master control interrupt lied (DE 
PIPE)!\n");
                        continue;
                }
 
                ret = IRQ_HANDLED;
-               I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir);
 
                if (iir & GEN8_PIPE_VBLANK)
                        drm_handle_vblank(&dev_priv->drm, pipe);
@@ -2960,28 +3090,22 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, 
u32 master_ctl)
 
        if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
            master_ctl & GEN8_DE_PCH_IRQ) {
-               struct pch_irq_regs pch = {};
+               u32 iir = pch->iir;
 
                /*
                 * FIXME(BDW): Assume for now that the new interrupt handling
                 * scheme also closed the SDE interrupt handling race we've seen
                 * on older pch-split platforms. But this needs testing.
                 */
-               pch.iir = I915_READ(SDEIIR);
-               if (pch.iir) {
-                       I915_WRITE(SDEIIR, pch.iir);
+               if (iir) {
                        ret = IRQ_HANDLED;
 
-                       if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) {
-                               icp_irq_ack(dev_priv, &pch);
-                               icp_irq_handler(dev_priv, &pch);
-                       } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) {
-                               spt_irq_ack(dev_priv, &pch);
-                               spt_irq_handler(dev_priv, &pch);
-                       } else {
-                               cpt_irq_ack(dev_priv, &pch);
-                               cpt_irq_handler(dev_priv, &pch);
-                       }
+                       if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+                               icp_irq_handler(dev_priv, pch);
+                       else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
+                               spt_irq_handler(dev_priv, pch);
+                       else
+                               cpt_irq_handler(dev_priv, pch);
                } else {
                        /*
                         * Like on previous PCH there seems to be something
@@ -3018,6 +3142,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        void __iomem * const regs = dev_priv->uncore.regs;
        u32 master_ctl;
        u32 gt_iir[4];
+       struct gen8_de_irq_regs de = {};
+       struct pch_irq_regs pch = {};
 
        if (!intel_irqs_enabled(dev_priv))
                return IRQ_NONE;
@@ -3034,7 +3160,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        /* IRQs are synced during runtime_suspend, we don't require a wakeref */
        if (master_ctl & ~GEN8_GT_IRQS) {
                disable_rpm_wakeref_asserts(dev_priv);
-               gen8_de_irq_handler(dev_priv, master_ctl);
+               gen8_de_irq_ack(dev_priv, master_ctl, &de, &pch);
                enable_rpm_wakeref_asserts(dev_priv);
        }
 
@@ -3042,6 +3168,12 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 
        gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir);
 
+       if (master_ctl & ~GEN8_GT_IRQS) {
+               disable_rpm_wakeref_asserts(dev_priv);
+               gen8_de_irq_handler(dev_priv, master_ctl, &de, &pch);
+               enable_rpm_wakeref_asserts(dev_priv);
+       }
+
        return IRQ_HANDLED;
 }
 
@@ -3214,6 +3346,9 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
        void __iomem * const regs = i915->uncore.regs;
        u32 master_ctl;
        u32 gu_misc_iir;
+       u32 disp_ctl = 0;
+       struct gen8_de_irq_regs de = {};
+       struct pch_irq_regs pch = {};
 
        if (!intel_irqs_enabled(i915))
                return IRQ_NONE;
@@ -3229,14 +3364,14 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
 
        /* IRQs are synced during runtime_suspend, we don't require a wakeref */
        if (master_ctl & GEN11_DISPLAY_IRQ) {
-               const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
+               disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
 
                disable_rpm_wakeref_asserts(i915);
                /*
                 * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
                 * for the display related bits.
                 */
-               gen8_de_irq_handler(i915, disp_ctl);
+               gen8_de_irq_ack(i915, disp_ctl, &de, &pch);
                enable_rpm_wakeref_asserts(i915);
        }
 
@@ -3244,6 +3379,16 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
 
        gen11_master_intr_enable(regs);
 
+       if (master_ctl & GEN11_DISPLAY_IRQ) {
+               disable_rpm_wakeref_asserts(i915);
+               /*
+                * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
+                * for the display related bits.
+                */
+               gen8_de_irq_handler(i915, disp_ctl, &de, &pch);
+               enable_rpm_wakeref_asserts(i915);
+       }
+
        gen11_gu_misc_irq_handler(i915, gu_misc_iir);
 
        return IRQ_HANDLED;
-- 
2.21.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to