diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 396 |
1 files changed, 246 insertions, 150 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 455b2bf691b5..b92cfd69134b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -28,16 +28,19 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/sysrq.h> -#include <linux/slab.h> -#include <linux/cpuidle.h> #include <linux/circ_buf.h> -#include <drm/drm_irq.h> +#include <linux/cpuidle.h> +#include <linux/slab.h> +#include <linux/sysrq.h> + #include <drm/drm_drv.h> +#include <drm/drm_irq.h> #include <drm/i915_drm.h> + #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include "intel_psr.h" /** * DOC: interrupt handling @@ -133,92 +136,120 @@ static const u32 hpd_icp[HPD_NUM_PINS] = { [HPD_PORT_F] = SDE_TC4_HOTPLUG_ICP }; -/* IIR can theoretically queue up two events. Be paranoid. */ -#define GEN8_IRQ_RESET_NDX(type, which) do { \ - I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ - POSTING_READ(GEN8_##type##_IMR(which)); \ - I915_WRITE(GEN8_##type##_IER(which), 0); \ - I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ - POSTING_READ(GEN8_##type##_IIR(which)); \ - I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ - POSTING_READ(GEN8_##type##_IIR(which)); \ -} while (0) - -#define GEN3_IRQ_RESET(type) do { \ - I915_WRITE(type##IMR, 0xffffffff); \ - POSTING_READ(type##IMR); \ - I915_WRITE(type##IER, 0); \ - I915_WRITE(type##IIR, 0xffffffff); \ - POSTING_READ(type##IIR); \ - I915_WRITE(type##IIR, 0xffffffff); \ - POSTING_READ(type##IIR); \ -} while (0) - -#define GEN2_IRQ_RESET(type) do { \ - I915_WRITE16(type##IMR, 0xffff); \ - POSTING_READ16(type##IMR); \ - I915_WRITE16(type##IER, 0); \ - I915_WRITE16(type##IIR, 0xffff); \ - POSTING_READ16(type##IIR); \ - I915_WRITE16(type##IIR, 0xffff); \ - POSTING_READ16(type##IIR); \ -} while (0) +static void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, + i915_reg_t iir, i915_reg_t ier) +{ + intel_uncore_write(uncore, imr, 0xffffffff); + intel_uncore_posting_read(uncore, imr); + + intel_uncore_write(uncore, ier, 0); + + /* IIR can theoretically queue up two events. Be paranoid. */ + intel_uncore_write(uncore, iir, 0xffffffff); + intel_uncore_posting_read(uncore, iir); + intel_uncore_write(uncore, iir, 0xffffffff); + intel_uncore_posting_read(uncore, iir); +} + +static void gen2_irq_reset(struct intel_uncore *uncore) +{ + intel_uncore_write16(uncore, GEN2_IMR, 0xffff); + intel_uncore_posting_read16(uncore, GEN2_IMR); + + intel_uncore_write16(uncore, GEN2_IER, 0); + + /* IIR can theoretically queue up two events. Be paranoid. */ + intel_uncore_write16(uncore, GEN2_IIR, 0xffff); + intel_uncore_posting_read16(uncore, GEN2_IIR); + intel_uncore_write16(uncore, GEN2_IIR, 0xffff); + intel_uncore_posting_read16(uncore, GEN2_IIR); +} + +#define GEN8_IRQ_RESET_NDX(uncore, type, which) \ +({ \ + unsigned int which_ = which; \ + gen3_irq_reset((uncore), GEN8_##type##_IMR(which_), \ + GEN8_##type##_IIR(which_), GEN8_##type##_IER(which_)); \ +}) + +#define GEN3_IRQ_RESET(uncore, type) \ + gen3_irq_reset((uncore), type##IMR, type##IIR, type##IER) + +#define GEN2_IRQ_RESET(uncore) \ + gen2_irq_reset(uncore) /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, - i915_reg_t reg) +static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) { - u32 val = I915_READ(reg); + u32 val = intel_uncore_read(uncore, reg); if (val == 0) return; WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", i915_mmio_reg_offset(reg), val); - I915_WRITE(reg, 0xffffffff); - POSTING_READ(reg); - I915_WRITE(reg, 0xffffffff); - POSTING_READ(reg); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); } -static void gen2_assert_iir_is_zero(struct drm_i915_private *dev_priv, - i915_reg_t reg) +static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) { - u16 val = I915_READ16(reg); + u16 val = intel_uncore_read16(uncore, GEN2_IIR); if (val == 0) return; WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", - i915_mmio_reg_offset(reg), val); - I915_WRITE16(reg, 0xffff); - POSTING_READ16(reg); - I915_WRITE16(reg, 0xffff); - POSTING_READ16(reg); -} - -#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ - gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ - I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ - I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ - POSTING_READ(GEN8_##type##_IMR(which)); \ -} while (0) - -#define GEN3_IRQ_INIT(type, imr_val, ier_val) do { \ - gen3_assert_iir_is_zero(dev_priv, type##IIR); \ - I915_WRITE(type##IER, (ier_val)); \ - I915_WRITE(type##IMR, (imr_val)); \ - POSTING_READ(type##IMR); \ -} while (0) - -#define GEN2_IRQ_INIT(type, imr_val, ier_val) do { \ - gen2_assert_iir_is_zero(dev_priv, type##IIR); \ - I915_WRITE16(type##IER, (ier_val)); \ - I915_WRITE16(type##IMR, (imr_val)); \ - POSTING_READ16(type##IMR); \ -} while (0) + i915_mmio_reg_offset(GEN2_IIR), val); + intel_uncore_write16(uncore, GEN2_IIR, 0xffff); + intel_uncore_posting_read16(uncore, GEN2_IIR); + intel_uncore_write16(uncore, GEN2_IIR, 0xffff); + intel_uncore_posting_read16(uncore, GEN2_IIR); +} + +static void gen3_irq_init(struct intel_uncore *uncore, + i915_reg_t imr, u32 imr_val, + i915_reg_t ier, u32 ier_val, + i915_reg_t iir) +{ + gen3_assert_iir_is_zero(uncore, iir); + + intel_uncore_write(uncore, ier, ier_val); + intel_uncore_write(uncore, imr, imr_val); + intel_uncore_posting_read(uncore, imr); +} + +static void gen2_irq_init(struct intel_uncore *uncore, + u32 imr_val, u32 ier_val) +{ + gen2_assert_iir_is_zero(uncore); + + intel_uncore_write16(uncore, GEN2_IER, ier_val); + intel_uncore_write16(uncore, GEN2_IMR, imr_val); + intel_uncore_posting_read16(uncore, GEN2_IMR); +} + +#define GEN8_IRQ_INIT_NDX(uncore, type, which, imr_val, ier_val) \ +({ \ + unsigned int which_ = which; \ + gen3_irq_init((uncore), \ + GEN8_##type##_IMR(which_), imr_val, \ + GEN8_##type##_IER(which_), ier_val, \ + GEN8_##type##_IIR(which_)); \ +}) + +#define GEN3_IRQ_INIT(uncore, type, imr_val, ier_val) \ + gen3_irq_init((uncore), \ + type##IMR, imr_val, \ + type##IER, ier_val, \ + type##IIR) + +#define GEN2_IRQ_INIT(uncore, imr_val, ier_val) \ + gen2_irq_init((uncore), imr_val, ier_val) static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); @@ -366,24 +397,41 @@ static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; } -static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) +static void write_pm_imr(struct drm_i915_private *dev_priv) { - if (INTEL_GEN(dev_priv) >= 11) - return GEN11_GPM_WGBOXPERF_INTR_MASK; - else if (INTEL_GEN(dev_priv) >= 8) - return GEN8_GT_IMR(2); - else - return GEN6_PMIMR; + i915_reg_t reg; + u32 mask = dev_priv->pm_imr; + + if (INTEL_GEN(dev_priv) >= 11) { + reg = GEN11_GPM_WGBOXPERF_INTR_MASK; + /* pm is in upper half */ + mask = mask << 16; + } else if (INTEL_GEN(dev_priv) >= 8) { + reg = GEN8_GT_IMR(2); + } else { + reg = GEN6_PMIMR; + } + + I915_WRITE(reg, mask); + POSTING_READ(reg); } -static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) +static void write_pm_ier(struct drm_i915_private *dev_priv) { - if (INTEL_GEN(dev_priv) >= 11) - return GEN11_GPM_WGBOXPERF_INTR_ENABLE; - else if (INTEL_GEN(dev_priv) >= 8) - return GEN8_GT_IER(2); - else - return GEN6_PMIER; + i915_reg_t reg; + u32 mask = dev_priv->pm_ier; + + if (INTEL_GEN(dev_priv) >= 11) { + reg = GEN11_GPM_WGBOXPERF_INTR_ENABLE; + /* pm is in upper half */ + mask = mask << 16; + } else if (INTEL_GEN(dev_priv) >= 8) { + reg = GEN8_GT_IER(2); + } else { + reg = GEN6_PMIER; + } + + I915_WRITE(reg, mask); } /** @@ -408,8 +456,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->pm_imr) { dev_priv->pm_imr = new_val; - I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr); - POSTING_READ(gen6_pm_imr(dev_priv)); + write_pm_imr(dev_priv); } } @@ -450,7 +497,7 @@ static void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mas lockdep_assert_held(&dev_priv->irq_lock); dev_priv->pm_ier |= enable_mask; - I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + write_pm_ier(dev_priv); gen6_unmask_pm_irq(dev_priv, enable_mask); /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ } @@ -461,7 +508,7 @@ static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_m dev_priv->pm_ier &= ~disable_mask; __gen6_mask_pm_irq(dev_priv, disable_mask); - I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + write_pm_ier(dev_priv); /* though a barrier is missing here, but don't really need a one */ } @@ -1470,7 +1517,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) if (iir & GT_RENDER_USER_INTERRUPT) { intel_engine_breadcrumbs_irq(engine); - tasklet |= USES_GUC_SUBMISSION(engine->i915); + tasklet |= intel_engine_needs_breadcrumb_tasklet(engine); } if (tasklet) @@ -1793,6 +1840,25 @@ static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ +static void gen11_rps_irq_handler(struct drm_i915_private *i915, u32 pm_iir) +{ + struct intel_rps *rps = &i915->gt_pm.rps; + const u32 events = i915->pm_rps_events & pm_iir; + + lockdep_assert_held(&i915->irq_lock); + + if (unlikely(!events)) + return; + + gen6_mask_pm_irq(i915, events); + + if (!rps->interrupts_enabled) + return; + + rps->pm_iir |= events; + schedule_work(&rps->work); +} + static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) { struct intel_rps *rps = &dev_priv->gt_pm.rps; @@ -2946,7 +3012,7 @@ gen11_other_irq_handler(struct drm_i915_private * const i915, const u8 instance, const u16 iir) { if (instance == OTHER_GTPM_INSTANCE) - return gen6_rps_irq_handler(i915, iir); + return gen11_rps_irq_handler(i915, iir); WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", instance, iir); @@ -3003,14 +3069,8 @@ gen11_gt_bank_handler(struct drm_i915_private * const i915, intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); - if (unlikely(!intr_dw)) { - DRM_ERROR("GT_INTR_DW%u blank!\n", bank); - return; - } - for_each_set_bit(bit, &intr_dw, 32) { - const u32 ident = gen11_gt_engine_identity(i915, - bank, bit); + const u32 ident = gen11_gt_engine_identity(i915, bank, bit); gen11_gt_identity_handler(i915, ident); } @@ -3305,10 +3365,12 @@ static void i945gm_vblank_work_fini(struct drm_i915_private *dev_priv) static void ibx_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; + if (HAS_PCH_NOP(dev_priv)) return; - GEN3_IRQ_RESET(SDE); + GEN3_IRQ_RESET(uncore, SDE); if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) I915_WRITE(SERR_INT, 0xffffffff); @@ -3336,13 +3398,17 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev) static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) { - GEN3_IRQ_RESET(GT); + struct intel_uncore *uncore = &dev_priv->uncore; + + GEN3_IRQ_RESET(uncore, GT); if (INTEL_GEN(dev_priv) >= 6) - GEN3_IRQ_RESET(GEN6_PM); + GEN3_IRQ_RESET(uncore, GEN6_PM); } static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; + if (IS_CHERRYVIEW(dev_priv)) I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else @@ -3353,12 +3419,14 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); - GEN3_IRQ_RESET(VLV_); + GEN3_IRQ_RESET(uncore, VLV_); dev_priv->irq_mask = ~0u; } static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; + u32 pipestat_mask; u32 enable_mask; enum pipe pipe; @@ -3383,7 +3451,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->irq_mask = ~enable_mask; - GEN3_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); + GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); } /* drm_dma.h hooks @@ -3391,8 +3459,9 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) static void ironlake_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; - GEN3_IRQ_RESET(DE); + GEN3_IRQ_RESET(uncore, DE); if (IS_GEN(dev_priv, 7)) I915_WRITE(GEN7_ERR_INT, 0xffffffff); @@ -3423,15 +3492,18 @@ static void valleyview_irq_reset(struct drm_device *dev) static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv) { - GEN8_IRQ_RESET_NDX(GT, 0); - GEN8_IRQ_RESET_NDX(GT, 1); - GEN8_IRQ_RESET_NDX(GT, 2); - GEN8_IRQ_RESET_NDX(GT, 3); + struct intel_uncore *uncore = &dev_priv->uncore; + + GEN8_IRQ_RESET_NDX(uncore, GT, 0); + GEN8_IRQ_RESET_NDX(uncore, GT, 1); + GEN8_IRQ_RESET_NDX(uncore, GT, 2); + GEN8_IRQ_RESET_NDX(uncore, GT, 3); } static void gen8_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; int pipe; gen8_master_intr_disable(dev_priv->uncore.regs); @@ -3444,11 +3516,11 @@ static void gen8_irq_reset(struct drm_device *dev) for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); + GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); - GEN3_IRQ_RESET(GEN8_DE_PORT_); - GEN3_IRQ_RESET(GEN8_DE_MISC_); - GEN3_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); + GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); + GEN3_IRQ_RESET(uncore, GEN8_PCU_); if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_reset(dev_priv); @@ -3474,6 +3546,7 @@ static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv) static void gen11_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_uncore *uncore = &dev_priv->uncore; int pipe; gen11_master_intr_disable(dev_priv->uncore.regs); @@ -3488,21 +3561,23 @@ static void gen11_irq_reset(struct drm_device *dev) for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); + GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); - GEN3_IRQ_RESET(GEN8_DE_PORT_); - GEN3_IRQ_RESET(GEN8_DE_MISC_); - GEN3_IRQ_RESET(GEN11_DE_HPD_); - GEN3_IRQ_RESET(GEN11_GU_MISC_); - GEN3_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); + GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); + GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); + GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); + GEN3_IRQ_RESET(uncore, GEN8_PCU_); if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - GEN3_IRQ_RESET(SDE); + GEN3_IRQ_RESET(uncore, SDE); } void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask) { + struct intel_uncore *uncore = &dev_priv->uncore; + u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; enum pipe pipe; @@ -3514,7 +3589,7 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, + GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, dev_priv->de_irq_mask[pipe], ~dev_priv->de_irq_mask[pipe] | extra_ier); @@ -3524,6 +3599,7 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask) { + struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; spin_lock_irq(&dev_priv->irq_lock); @@ -3534,7 +3610,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); + GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); spin_unlock_irq(&dev_priv->irq_lock); @@ -3545,13 +3621,14 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, static void cherryview_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; I915_WRITE(GEN8_MASTER_IRQ, 0); POSTING_READ(GEN8_MASTER_IRQ); gen8_gt_irq_reset(dev_priv); - GEN3_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(uncore, GEN8_PCU_); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display_irqs_enabled) @@ -3823,7 +3900,7 @@ static void ibx_irq_postinstall(struct drm_device *dev) else mask = SDE_GMBUS_CPT; - gen3_assert_iir_is_zero(dev_priv, SDEIIR); + gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); I915_WRITE(SDEIMR, ~mask); if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || @@ -3836,6 +3913,7 @@ static void ibx_irq_postinstall(struct drm_device *dev) static void gen5_gt_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; u32 pm_irqs, gt_irqs; pm_irqs = gt_irqs = 0; @@ -3854,7 +3932,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; } - GEN3_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); + GEN3_IRQ_INIT(uncore, GT, dev_priv->gt_irq_mask, gt_irqs); if (INTEL_GEN(dev_priv) >= 6) { /* @@ -3867,13 +3945,14 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) } dev_priv->pm_imr = 0xffffffff; - GEN3_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); + GEN3_IRQ_INIT(uncore, GEN6_PM, dev_priv->pm_imr, pm_irqs); } } static int ironlake_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; u32 display_mask, extra_mask; if (INTEL_GEN(dev_priv) >= 7) { @@ -3892,7 +3971,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) } if (IS_HASWELL(dev_priv)) { - gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); + gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); intel_psr_irq_control(dev_priv, dev_priv->psr.debug); display_mask |= DE_EDP_PSR_INT_HSW; } @@ -3901,7 +3980,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ibx_irq_pre_postinstall(dev); - GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); + GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, + display_mask | extra_mask); gen5_gt_irq_postinstall(dev); @@ -3971,6 +4051,8 @@ static int valleyview_irq_postinstall(struct drm_device *dev) static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; + /* These are interrupts we'll toggle with the ring mask register */ u32 gt_interrupts[] = { (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | @@ -3991,18 +4073,20 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->pm_ier = 0x0; dev_priv->pm_imr = ~dev_priv->pm_ier; - GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); - GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); + GEN8_IRQ_INIT_NDX(uncore, GT, 0, ~gt_interrupts[0], gt_interrupts[0]); + GEN8_IRQ_INIT_NDX(uncore, GT, 1, ~gt_interrupts[1], gt_interrupts[1]); /* * RPS interrupts will get enabled/disabled on demand when RPS itself * is enabled/disabled. Same wil be the case for GuC interrupts. */ - GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); - GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); + GEN8_IRQ_INIT_NDX(uncore, GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); + GEN8_IRQ_INIT_NDX(uncore, GT, 3, ~gt_interrupts[3], gt_interrupts[3]); } static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; + u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; u32 de_pipe_enables; u32 de_port_masked = GEN8_AUX_CHANNEL_A; @@ -4038,7 +4122,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) else if (IS_BROADWELL(dev_priv)) de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; - gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); + gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); intel_psr_irq_control(dev_priv, dev_priv->psr.debug); for_each_pipe(dev_priv, pipe) { @@ -4046,20 +4130,21 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) - GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, + GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, dev_priv->de_irq_mask[pipe], de_pipe_enables); } - GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); - GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); + GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); + GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); if (INTEL_GEN(dev_priv) >= 11) { u32 de_hpd_masked = 0; u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; - GEN3_IRQ_INIT(GEN11_DE_HPD_, ~de_hpd_masked, de_hpd_enables); + GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, + de_hpd_enables); gen11_hpd_detection_setup(dev_priv); } else if (IS_GEN9_LP(dev_priv)) { bxt_hpd_detection_setup(dev_priv); @@ -4122,7 +4207,7 @@ static void icp_irq_postinstall(struct drm_device *dev) I915_WRITE(SDEIER, 0xffffffff); POSTING_READ(SDEIER); - gen3_assert_iir_is_zero(dev_priv, SDEIIR); + gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); I915_WRITE(SDEIMR, ~mask); icp_hpd_detection_setup(dev_priv); @@ -4131,6 +4216,7 @@ static void icp_irq_postinstall(struct drm_device *dev) static int gen11_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_uncore *uncore = &dev_priv->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) @@ -4139,7 +4225,7 @@ static int gen11_irq_postinstall(struct drm_device *dev) gen11_gt_irq_postinstall(dev_priv); gen8_de_irq_postinstall(dev_priv); - GEN3_IRQ_INIT(GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); + GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); @@ -4169,15 +4255,17 @@ static int cherryview_irq_postinstall(struct drm_device *dev) static void i8xx_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; i9xx_pipestat_irq_reset(dev_priv); - GEN2_IRQ_RESET(); + GEN2_IRQ_RESET(uncore); } static int i8xx_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; u16 enable_mask; I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | @@ -4195,7 +4283,7 @@ static int i8xx_irq_postinstall(struct drm_device *dev) I915_MASTER_ERROR_INTERRUPT | I915_USER_INTERRUPT; - GEN2_IRQ_INIT(, dev_priv->irq_mask, enable_mask); + GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -4299,7 +4387,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) u16 eir = 0, eir_stuck = 0; u16 iir; - iir = I915_READ16(IIR); + iir = I915_READ16(GEN2_IIR); if (iir == 0) break; @@ -4312,7 +4400,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_MASTER_ERROR_INTERRUPT) i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); - I915_WRITE16(IIR, iir); + I915_WRITE16(GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); @@ -4331,6 +4419,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) static void i915_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); @@ -4339,12 +4428,13 @@ static void i915_irq_reset(struct drm_device *dev) i9xx_pipestat_irq_reset(dev_priv); - GEN3_IRQ_RESET(); + GEN3_IRQ_RESET(uncore, GEN2_); } static int i915_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | @@ -4371,7 +4461,7 @@ static int i915_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; } - GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); + GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -4403,7 +4493,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) u32 hotplug_status = 0; u32 iir; - iir = I915_READ(IIR); + iir = I915_READ(GEN2_IIR); if (iir == 0) break; @@ -4420,7 +4510,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); - I915_WRITE(IIR, iir); + I915_WRITE(GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); @@ -4442,18 +4532,20 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) static void i965_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); i9xx_pipestat_irq_reset(dev_priv); - GEN3_IRQ_RESET(); + GEN3_IRQ_RESET(uncore, GEN2_); } static int i965_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; u32 error_mask; @@ -4491,7 +4583,7 @@ static int i965_irq_postinstall(struct drm_device *dev) if (IS_G4X(dev_priv)) enable_mask |= I915_BSD_USER_INTERRUPT; - GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); + GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -4549,7 +4641,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) u32 hotplug_status = 0; u32 iir; - iir = I915_READ(IIR); + iir = I915_READ(GEN2_IIR); if (iir == 0) break; @@ -4565,7 +4657,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); - I915_WRITE(IIR, iir); + I915_WRITE(GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); @@ -4623,6 +4715,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT); + /* We share the register with other engine */ + if (INTEL_GEN(dev_priv) > 9) + GEM_WARN_ON(dev_priv->pm_rps_events & 0xffff0000); + rps->pm_intrmsk_mbz = 0; /* |