From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Optimize the irq handlers a bit by switching to the raw register access functions. It seems we can go fully lockless due to WaSerializeKmdDisplayAccess, so in order to protect against that we grab the irq_lock around the ack. I *think* that should be sufficient as that's held whenever we otherwise massage the irq registers. The w/a database lists this only for snb/ivb/hsw, so maybe we don't even need it for bdw+? But I was too chicken to leave it out. This leads to some shrinkage: add/remove: 1/5 grow/shrink: 3/2 up/down: 183/-1307 (-1124) Function old new delta gen8_gt_irq_ack - 104 +104 gen8_irq_handler 291 334 +43 gen11_irq_handler 902 935 +33 cherryview_irq_handler 636 639 +3 ilk_hpd_irq_ack.isra 82 - -82 hsw_psr_irq_ack 91 - -91 gen8_gt_irq_ack.isra 104 - -104 ibx_hpd_irq_ack.isra 106 - -106 cpt_irq_ack 117 - -117 ironlake_irq_handler 2973 2700 -273 gen8_de_irq_ack 1229 695 -534 Total: Before=34132, After=33008, chg -3.29% so we're now below the original pre-ack/handle split numbers. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_irq.c | 220 +++++++++++++++++--------------- 1 file changed, 119 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b83c9d71d630..2ed715d4bddd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1577,11 +1577,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) tasklet_hi_schedule(&engine->execlists.tasklet); } -static void gen8_gt_irq_ack(struct drm_i915_private *i915, +static void gen8_gt_irq_ack(void __iomem * const regs, u32 master_ctl, u32 gt_iir[4]) { - void __iomem * const regs = i915->uncore.regs; - #define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ GEN8_GT_BCS_IRQ | \ GEN8_GT_VCS0_IRQ | \ @@ -2293,6 +2291,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); do { + void __iomem * const regs = dev_priv->uncore.regs; u32 master_ctl, iir; u32 pipe_stats[I915_MAX_PIPES] = {}; u32 hotplug_status = 0; @@ -2324,7 +2323,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) ier = I915_READ(VLV_IER); I915_WRITE(VLV_IER, 0); - gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); + gen8_gt_irq_ack(regs, master_ctl, gt_iir); if (iir & I915_DISPLAY_PORT_INTERRUPT) hotplug_status = i9xx_hpd_irq_ack(dev_priv); @@ -2381,7 +2380,7 @@ struct pch_irq_regs { }; }; -static void ibx_hpd_irq_ack(struct drm_i915_private *dev_priv, +static void ibx_hpd_irq_ack(void __iomem * const regs, struct hpd_irq_regs *hpd) { /* @@ -2390,7 +2389,7 @@ static void ibx_hpd_irq_ack(struct drm_i915_private *dev_priv, * zero. Not acking leads to "The master control interrupt lied (SDE)!" * errors. */ - hpd->dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + hpd->dig_hotplug_reg = raw_reg_read(regs, PCH_PORT_HOTPLUG); if (!hpd->hotplug_trigger) { u32 mask = PORTA_HOTPLUG_STATUS_MASK | PORTD_HOTPLUG_STATUS_MASK | @@ -2399,7 +2398,7 @@ static void ibx_hpd_irq_ack(struct drm_i915_private *dev_priv, hpd->dig_hotplug_reg &= ~mask; } - I915_WRITE(PCH_PORT_HOTPLUG, hpd->dig_hotplug_reg); + raw_reg_write(regs, PCH_PORT_HOTPLUG, hpd->dig_hotplug_reg); } static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, @@ -2417,12 +2416,12 @@ static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); } -static void ibx_irq_ack(struct drm_i915_private *dev_priv, +static void ibx_irq_ack(void __iomem * const regs, struct pch_irq_regs *pch) { pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK; - ibx_hpd_irq_ack(dev_priv, &pch->hpd); + ibx_hpd_irq_ack(regs, &pch->hpd); } static void ibx_irq_handler(struct drm_i915_private *dev_priv, @@ -2474,11 +2473,11 @@ 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_ack(struct drm_i915_private *dev_priv, +static void ivb_err_int_ack(void __iomem * const regs, struct ilk_de_irq_regs *de) { - de->err_int = I915_READ(GEN7_ERR_INT); - I915_WRITE(GEN7_ERR_INT, de->err_int); + de->err_int = raw_reg_read(regs, GEN7_ERR_INT); + raw_reg_write(regs, GEN7_ERR_INT, de->err_int); } static void ivb_err_int_handler(struct drm_i915_private *dev_priv, @@ -2503,11 +2502,11 @@ static void ivb_err_int_handler(struct drm_i915_private *dev_priv, } } -static void cpt_serr_int_ack(struct drm_i915_private *dev_priv, +static void cpt_serr_int_ack(void __iomem * const regs, struct pch_irq_regs *pch) { - pch->serr_int = I915_READ(SERR_INT); - I915_WRITE(SERR_INT, pch->serr_int); + pch->serr_int = raw_reg_read(regs, SERR_INT); + raw_reg_write(regs, SERR_INT, pch->serr_int); } static void cpt_serr_int_handler(struct drm_i915_private *dev_priv, @@ -2524,15 +2523,15 @@ static void cpt_serr_int_handler(struct drm_i915_private *dev_priv, intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); } -static void cpt_irq_ack(struct drm_i915_private *dev_priv, +static void cpt_irq_ack(void __iomem * const regs, struct pch_irq_regs *pch) { pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK_CPT; - ibx_hpd_irq_ack(dev_priv, &pch->hpd); + ibx_hpd_irq_ack(regs, &pch->hpd); if (pch->iir & SDE_ERROR_CPT) - cpt_serr_int_ack(dev_priv, pch); + cpt_serr_int_ack(regs, pch); } static void cpt_irq_handler(struct drm_i915_private *dev_priv, @@ -2572,20 +2571,20 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, cpt_serr_int_handler(dev_priv, pch); } -static void icp_irq_ack(struct drm_i915_private *dev_priv, +static void icp_irq_ack(void __iomem * const regs, struct pch_irq_regs *pch) { pch->ddi.hotplug_trigger = pch->iir & SDE_DDI_MASK_ICP; pch->tc.hotplug_trigger = pch->iir & SDE_TC_MASK_ICP; if (pch->ddi.hotplug_trigger) { - pch->ddi.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); - I915_WRITE(SHOTPLUG_CTL_DDI, pch->ddi.dig_hotplug_reg); + pch->ddi.dig_hotplug_reg = raw_reg_read(regs, SHOTPLUG_CTL_DDI); + raw_reg_write(regs, SHOTPLUG_CTL_DDI, pch->ddi.dig_hotplug_reg); } if (pch->tc.hotplug_trigger) { - pch->tc.dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); - I915_WRITE(SHOTPLUG_CTL_TC, pch->tc.dig_hotplug_reg); + pch->tc.dig_hotplug_reg = raw_reg_read(regs, SHOTPLUG_CTL_TC); + raw_reg_write(regs, SHOTPLUG_CTL_TC, pch->tc.dig_hotplug_reg); } } @@ -2615,7 +2614,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, gmbus_irq_handler(dev_priv); } -static void spt_irq_ack(struct drm_i915_private *dev_priv, +static void spt_irq_ack(void __iomem * const regs, struct pch_irq_regs *pch) { pch->hpd.hotplug_trigger = pch->iir & SDE_HOTPLUG_MASK_SPT & @@ -2623,13 +2622,13 @@ static void spt_irq_ack(struct drm_i915_private *dev_priv, pch->hpd2.hotplug_trigger = pch->iir & SDE_PORTE_HOTPLUG_SPT; if (pch->hpd.hotplug_trigger) { - pch->hpd.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); - I915_WRITE(PCH_PORT_HOTPLUG, pch->hpd.dig_hotplug_reg); + pch->hpd.dig_hotplug_reg = raw_reg_read(regs, PCH_PORT_HOTPLUG); + raw_reg_write(regs, PCH_PORT_HOTPLUG, pch->hpd.dig_hotplug_reg); } if (pch->hpd2.hotplug_trigger) { - pch->hpd2.dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); - I915_WRITE(PCH_PORT_HOTPLUG2, pch->hpd2.dig_hotplug_reg); + pch->hpd2.dig_hotplug_reg = raw_reg_read(regs, PCH_PORT_HOTPLUG2); + raw_reg_write(regs, PCH_PORT_HOTPLUG2, pch->hpd2.dig_hotplug_reg); } } @@ -2658,11 +2657,11 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, gmbus_irq_handler(dev_priv); } -static void ilk_hpd_irq_ack(struct drm_i915_private *dev_priv, +static void ilk_hpd_irq_ack(void __iomem * const regs, struct hpd_irq_regs *hpd) { - hpd->dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); - I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hpd->dig_hotplug_reg); + hpd->dig_hotplug_reg = raw_reg_read(regs, DIGITAL_PORT_HOTPLUG_CNTRL); + raw_reg_write(regs, DIGITAL_PORT_HOTPLUG_CNTRL, hpd->dig_hotplug_reg); } static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, @@ -2678,26 +2677,27 @@ 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, +static void ilk_display_irq_ack(struct drm_i915_private *i915, + void __iomem * const regs, 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); + ilk_hpd_irq_ack(regs, &de->hpd); /* check event from PCH */ if (de->iir & DE_PCH_EVENT) { - pch->iir = I915_READ(SDEIIR); + pch->iir = raw_reg_read(regs, SDEIIR); - if (HAS_PCH_CPT(dev_priv)) - cpt_irq_ack(dev_priv, pch); + if (HAS_PCH_CPT(i915)) + cpt_irq_ack(regs, pch); else - ibx_irq_ack(dev_priv, pch); + ibx_irq_ack(regs, pch); /* should clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch->iir); + raw_reg_write(regs, SDEIIR, pch->iir); } } @@ -2743,37 +2743,38 @@ static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, ironlake_rps_change_irq_handler(dev_priv); } -static void hsw_psr_irq_ack(struct drm_i915_private *dev_priv, +static void hsw_psr_irq_ack(void __iomem * const regs, u32 *psr_iir) { - *psr_iir = I915_READ(EDP_PSR_IIR); + *psr_iir = raw_reg_read(regs, EDP_PSR_IIR); if (*psr_iir) - I915_WRITE(EDP_PSR_IIR, *psr_iir); + raw_reg_write(regs, EDP_PSR_IIR, *psr_iir); } -static void ivb_display_irq_ack(struct drm_i915_private *dev_priv, +static void ivb_display_irq_ack(struct drm_i915_private *i915, + void __iomem * const regs, 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); + ilk_hpd_irq_ack(regs, &de->hpd); if (de->iir & DE_ERR_INT_IVB) - ivb_err_int_ack(dev_priv, de); + ivb_err_int_ack(regs, de); if (de->iir & DE_EDP_PSR_INT_HSW) - hsw_psr_irq_ack(dev_priv, &de->psr_iir); + hsw_psr_irq_ack(regs, &de->psr_iir); /* check event from PCH */ - if (!HAS_PCH_NOP(dev_priv) && de->iir & DE_PCH_EVENT_IVB) { - pch->iir = I915_READ(SDEIIR); + if (!HAS_PCH_NOP(i915) && de->iir & DE_PCH_EVENT_IVB) { + pch->iir = raw_reg_read(regs, SDEIIR); - cpt_irq_ack(dev_priv, pch); + cpt_irq_ack(regs, pch); /* clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch->iir); + raw_reg_write(regs, SDEIIR, pch->iir); } } @@ -2820,6 +2821,7 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, static irqreturn_t ironlake_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; + void __iomem * const regs = dev_priv->uncore.regs; u32 gt_iir, pm_iir = 0, de_ier, sde_ier = 0; struct ilk_de_irq_regs de; struct pch_irq_regs pch; @@ -2831,9 +2833,12 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); + /* WaSerializeKmdDisplayAccess:snb,ivb,hsw */ + spin_lock(&dev_priv->irq_lock); + /* disable master interrupt before clearing iir */ - de_ier = I915_READ(DEIER); - I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); + de_ier = raw_reg_read(regs, DEIER); + raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); /* 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 @@ -2841,35 +2846,37 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) * it, we'll get an interrupt if SDEIIR still has something to process * due to its back queue). */ if (!HAS_PCH_NOP(dev_priv)) { - sde_ier = I915_READ(SDEIER); - I915_WRITE(SDEIER, 0); + sde_ier = raw_reg_read(regs, SDEIER); + raw_reg_write(regs, SDEIER, 0); } /* Find, clear, then process each source of interrupt */ - gt_iir = I915_READ(GTIIR); - de.iir = I915_READ(DEIIR); + gt_iir = raw_reg_read(regs, GTIIR); + de.iir = raw_reg_read(regs, DEIIR); if (INTEL_GEN(dev_priv) >= 6) - pm_iir = I915_READ(GEN6_PMIIR); + pm_iir = raw_reg_read(regs, GEN6_PMIIR); if (gt_iir) - I915_WRITE(GTIIR, gt_iir); + raw_reg_write(regs, GTIIR, gt_iir); if (de.iir) { if (INTEL_GEN(dev_priv) >= 7) - ivb_display_irq_ack(dev_priv, &de, &pch); + ivb_display_irq_ack(dev_priv, regs, &de, &pch); else - ilk_display_irq_ack(dev_priv, &de, &pch); + ilk_display_irq_ack(dev_priv, regs, &de, &pch); - I915_WRITE(DEIIR, de.iir); + raw_reg_write(regs, DEIIR, de.iir); } if (pm_iir) - I915_WRITE(GEN6_PMIIR, pm_iir); + raw_reg_write(regs, GEN6_PMIIR, pm_iir); - I915_WRITE(DEIER, de_ier); + raw_reg_write(regs, DEIER, de_ier); if (!HAS_PCH_NOP(dev_priv)) - I915_WRITE(SDEIER, sde_ier); + raw_reg_write(regs, SDEIER, sde_ier); + + spin_unlock(&dev_priv->irq_lock); if (gt_iir) { ret = IRQ_HANDLED; @@ -2898,11 +2905,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } -static void bxt_hpd_irq_ack(struct drm_i915_private *dev_priv, +static void bxt_hpd_irq_ack(void __iomem * const regs, struct hpd_irq_regs *hpd) { - hpd->dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); - I915_WRITE(PCH_PORT_HOTPLUG, hpd->dig_hotplug_reg); + hpd->dig_hotplug_reg = raw_reg_read(regs, PCH_PORT_HOTPLUG); + raw_reg_write(regs, PCH_PORT_HOTPLUG, hpd->dig_hotplug_reg); } static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, @@ -2928,20 +2935,20 @@ struct gen8_de_irq_regs { struct hpd_irq_regs tc, tbt; /* icl+ */ }; -static void gen11_hpd_irq_ack(struct drm_i915_private *dev_priv, +static void gen11_hpd_irq_ack(void __iomem * const regs, 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); + de->tc.dig_hotplug_reg = raw_reg_read(regs, GEN11_TC_HOTPLUG_CTL); + raw_reg_write(regs, 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); + de->tbt.dig_hotplug_reg = raw_reg_read(regs, GEN11_TBT_HOTPLUG_CTL); + raw_reg_write(regs, GEN11_TBT_HOTPLUG_CTL, de->tbt.dig_hotplug_reg); } } @@ -2969,76 +2976,77 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, } static void -gen8_de_irq_ack(struct drm_i915_private *dev_priv, u32 master_ctl, +gen8_de_irq_ack(struct drm_i915_private *i915, + void __iomem * const regs, 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); + de->misc_iir = raw_reg_read(regs, 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); + hsw_psr_irq_ack(regs, &de->psr_iir); - I915_WRITE(GEN8_DE_MISC_IIR, de->misc_iir); + raw_reg_write(regs, GEN8_DE_MISC_IIR, de->misc_iir); } } if (master_ctl & GEN11_DE_HPD_IRQ) { - de->hpd_iir = I915_READ(GEN11_DE_HPD_IIR); + de->hpd_iir = raw_reg_read(regs, GEN11_DE_HPD_IIR); if (de->hpd_iir) { - gen11_hpd_irq_ack(dev_priv, de); + gen11_hpd_irq_ack(regs, de); - I915_WRITE(GEN11_DE_HPD_IIR, de->hpd_iir); + raw_reg_write(regs, GEN11_DE_HPD_IIR, de->hpd_iir); } } if (master_ctl & GEN8_DE_PORT_IRQ) { - de->port_iir = I915_READ(GEN8_DE_PORT_IIR); + de->port_iir = raw_reg_read(regs, GEN8_DE_PORT_IIR); if (de->port_iir) { - if (IS_GEN9_LP(dev_priv)) { + if (IS_GEN9_LP(i915)) { 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)) { + bxt_hpd_irq_ack(regs, &de->ddi); + } else if (IS_BROADWELL(i915)) { 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); + ilk_hpd_irq_ack(regs, &de->ddi); } - I915_WRITE(GEN8_DE_PORT_IIR, de->port_iir); + raw_reg_write(regs, GEN8_DE_PORT_IIR, de->port_iir); } } - for_each_pipe(dev_priv, pipe) { + for_each_pipe(i915, pipe) { if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) continue; - de->pipe_iir[pipe] = I915_READ(GEN8_DE_PIPE_IIR(pipe)); + de->pipe_iir[pipe] = raw_reg_read(regs, GEN8_DE_PIPE_IIR(pipe)); if (de->pipe_iir[pipe]) - I915_WRITE(GEN8_DE_PIPE_IIR(pipe), de->pipe_iir[pipe]); + raw_reg_write(regs, GEN8_DE_PIPE_IIR(pipe), de->pipe_iir[pipe]); } - if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && + if (HAS_PCH_SPLIT(i915) && !HAS_PCH_NOP(i915) && 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); + pch->iir = raw_reg_read(regs, SDEIIR); if (pch->iir) { - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_irq_ack(dev_priv, pch); - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) - spt_irq_ack(dev_priv, pch); + if (INTEL_PCH_TYPE(i915) >= PCH_ICP) + icp_irq_ack(regs, pch); + else if (INTEL_PCH_TYPE(i915) >= PCH_SPT) + spt_irq_ack(regs, pch); else - cpt_irq_ack(dev_priv, pch); + cpt_irq_ack(regs, pch); - I915_WRITE(SDEIIR, pch->iir); + raw_reg_write(regs, SDEIIR, pch->iir); } } } @@ -3235,24 +3243,29 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + spin_lock(&dev_priv->irq_lock); + master_ctl = gen8_master_intr_disable(regs); if (!master_ctl) { gen8_master_intr_enable(regs); + spin_unlock(&dev_priv->irq_lock); return IRQ_NONE; } /* Find, clear, then process each source of interrupt */ - gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); + gen8_gt_irq_ack(regs, master_ctl, gt_iir); /* IRQs are synced during runtime_suspend, we don't require a wakeref */ if (master_ctl & ~GEN8_GT_IRQS) { disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); - gen8_de_irq_ack(dev_priv, master_ctl, &de, &pch); + gen8_de_irq_ack(dev_priv, regs, master_ctl, &de, &pch); enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); } gen8_master_intr_enable(regs); + spin_unlock(&dev_priv->irq_lock); + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); if (master_ctl & ~GEN8_GT_IRQS) { @@ -3390,9 +3403,9 @@ gen11_gt_irq_handler(struct drm_i915_private * const i915, } static u32 -gen11_gu_misc_irq_ack(struct drm_i915_private *dev_priv, const u32 master_ctl) +gen11_gu_misc_irq_ack(void __iomem * const regs, + u32 master_ctl) { - void __iomem * const regs = dev_priv->uncore.regs; u32 iir; if (!(master_ctl & GEN11_GU_MISC_IRQ)) @@ -3443,9 +3456,12 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(i915)) return IRQ_NONE; + spin_lock(&i915->irq_lock); + master_ctl = gen11_master_intr_disable(regs); if (!master_ctl) { gen11_master_intr_enable(regs); + spin_unlock(&i915->irq_lock); return IRQ_NONE; } @@ -3461,14 +3477,16 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ * for the display related bits. */ - gen8_de_irq_ack(i915, disp_ctl, &de, &pch); + gen8_de_irq_ack(i915, regs, disp_ctl, &de, &pch); enable_rpm_wakeref_asserts(&i915->runtime_pm); } - gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); + gu_misc_iir = gen11_gu_misc_irq_ack(regs, master_ctl); gen11_master_intr_enable(regs); + spin_unlock(&i915->irq_lock); + if (master_ctl & GEN11_DISPLAY_IRQ) { disable_rpm_wakeref_asserts(&i915->runtime_pm); /* -- 2.21.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx