diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 293 |
1 files changed, 138 insertions, 155 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 390ccc2a3096..f66392b6e287 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) { assert_spin_locked(&dev_priv->irq_lock); - if (!intel_irqs_enabled(dev_priv)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; if ((dev_priv->irq_mask & mask) != mask) { @@ -238,7 +238,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); if (crtc->cpu_fifo_underrun_disabled) @@ -296,7 +296,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); if (crtc->pch_fifo_underrun_disabled) @@ -497,7 +497,7 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, old = !intel_crtc->cpu_fifo_underrun_disabled; intel_crtc->cpu_fifo_underrun_disabled = !enable; - if (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)) + if (HAS_GMCH_DISPLAY(dev)) i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); else if (IS_GEN5(dev) || IS_GEN6(dev)) ironlake_set_fifo_underrun_reporting(dev, pipe, enable); @@ -1020,7 +1020,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, /* In vblank? */ if (in_vbl) - ret |= DRM_SCANOUTPOS_INVBL; + ret |= DRM_SCANOUTPOS_IN_VBLANK; return ret; } @@ -1189,8 +1189,8 @@ static void i915_hotplug_work_func(struct work_struct *work) * some connectors */ if (hpd_disabled) { drm_kms_helper_poll_enable(dev); - mod_timer(&dev_priv->hotplug_reenable_timer, - jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY)); + mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work, + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY)); } spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); @@ -1213,11 +1213,6 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_kms_helper_hotplug_event(dev); } -static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv) -{ - del_timer_sync(&dev_priv->hotplug_reenable_timer); -} - static void ironlake_rps_change_irq_handler(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1327,10 +1322,10 @@ static u32 vlv_c0_residency(struct drm_i915_private *dev_priv, * @dev_priv: DRM device private * */ -static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv) +static int vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv) { u32 residency_C0_up = 0, residency_C0_down = 0; - u8 new_delay, adj; + int new_delay, adj; dev_priv->rps.ei_interrupt_count++; @@ -1632,6 +1627,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 master_ctl) { + struct intel_engine_cs *ring; u32 rcs, bcs, vcs; uint32_t tmp = 0; irqreturn_t ret = IRQ_NONE; @@ -1641,12 +1637,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (tmp) { I915_WRITE(GEN8_GT_IIR(0), tmp); ret = IRQ_HANDLED; + rcs = tmp >> GEN8_RCS_IRQ_SHIFT; - bcs = tmp >> GEN8_BCS_IRQ_SHIFT; + ring = &dev_priv->ring[RCS]; if (rcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[RCS]); + notify_ring(dev, ring); + if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) + intel_execlists_handle_ctx_events(ring); + + bcs = tmp >> GEN8_BCS_IRQ_SHIFT; + ring = &dev_priv->ring[BCS]; if (bcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[BCS]); + notify_ring(dev, ring); + if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) + intel_execlists_handle_ctx_events(ring); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } @@ -1656,12 +1660,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (tmp) { I915_WRITE(GEN8_GT_IIR(1), tmp); ret = IRQ_HANDLED; + vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; + ring = &dev_priv->ring[VCS]; if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS]); + notify_ring(dev, ring); + if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) + intel_execlists_handle_ctx_events(ring); + vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; + ring = &dev_priv->ring[VCS2]; if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS2]); + notify_ring(dev, ring); + if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) + intel_execlists_handle_ctx_events(ring); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } @@ -1682,9 +1694,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (tmp) { I915_WRITE(GEN8_GT_IIR(3), tmp); ret = IRQ_HANDLED; + vcs = tmp >> GEN8_VECS_IRQ_SHIFT; + ring = &dev_priv->ring[VECS]; if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VECS]); + notify_ring(dev, ring); + if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) + intel_execlists_handle_ctx_events(ring); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } @@ -1695,7 +1711,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, #define HPD_STORM_DETECT_PERIOD 1000 #define HPD_STORM_THRESHOLD 5 -static int ilk_port_to_hotplug_shift(enum port port) +static int pch_port_to_hotplug_shift(enum port port) { switch (port) { case PORT_A: @@ -1711,7 +1727,7 @@ static int ilk_port_to_hotplug_shift(enum port port) } } -static int g4x_port_to_hotplug_shift(enum port port) +static int i915_port_to_hotplug_shift(enum port port) { switch (port) { case PORT_A: @@ -1769,15 +1785,17 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev, if (port && dev_priv->hpd_irq_port[port]) { bool long_hpd; - if (IS_G4X(dev)) { - dig_shift = g4x_port_to_hotplug_shift(port); - long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT; - } else { - dig_shift = ilk_port_to_hotplug_shift(port); + if (HAS_PCH_SPLIT(dev)) { + dig_shift = pch_port_to_hotplug_shift(port); long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT; + } else { + dig_shift = i915_port_to_hotplug_shift(port); + long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT; } - DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port, long_hpd); + DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", + port_name(port), + long_hpd ? "long" : "short"); /* for long HPD pulses we want to have the digital queue happen, but we still want HPD storm detection to function. */ if (long_hpd) { @@ -1989,14 +2007,9 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) static bool intel_pipe_handle_vblank(struct drm_device *dev, enum pipe pipe) { - struct intel_crtc *crtc; - if (!drm_handle_vblank(dev, pipe)) return false; - crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); - wake_up(&crtc->vbl_wait); - return true; } @@ -2007,7 +2020,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) int pipe; spin_lock(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg; u32 mask, iir_bit = 0; @@ -2052,9 +2065,10 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) } spin_unlock(&dev_priv->irq_lock); - for_each_pipe(pipe) { - if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) - intel_pipe_handle_vblank(dev, pipe); + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && + intel_pipe_handle_vblank(dev, pipe)) + intel_check_page_flip(dev, pipe); if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) { intel_prepare_page_flip(dev, pipe); @@ -2221,7 +2235,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_ERROR("PCH poison interrupt\n"); if (pch_iir & SDE_FDI_MASK) - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), I915_READ(FDI_RX_IIR(pipe))); @@ -2252,7 +2266,7 @@ static void ivb_err_int_handler(struct drm_device *dev) if (err_int & ERR_INT_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) { if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) @@ -2329,7 +2343,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); if (pch_iir & SDE_FDI_MASK_CPT) - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), I915_READ(FDI_RX_IIR(pipe))); @@ -2352,9 +2366,10 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { - if (de_iir & DE_PIPE_VBLANK(pipe)) - intel_pipe_handle_vblank(dev, pipe); + for_each_pipe(dev_priv, pipe) { + if (de_iir & DE_PIPE_VBLANK(pipe) && + intel_pipe_handle_vblank(dev, pipe)) + intel_check_page_flip(dev, pipe); if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) @@ -2402,9 +2417,10 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE_IVB) intel_opregion_asle_intr(dev); - for_each_pipe(pipe) { - if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) - intel_pipe_handle_vblank(dev, pipe); + for_each_pipe(dev_priv, pipe) { + if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)) && + intel_pipe_handle_vblank(dev, pipe)) + intel_check_page_flip(dev, pipe); /* plane/pipes map 1:1 on ilk+ */ if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) { @@ -2549,7 +2565,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); } - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { uint32_t pipe_iir; if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) @@ -2559,8 +2575,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (pipe_iir) { ret = IRQ_HANDLED; I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir); - if (pipe_iir & GEN8_PIPE_VBLANK) - intel_pipe_handle_vblank(dev, pipe); + if (pipe_iir & GEN8_PIPE_VBLANK && + intel_pipe_handle_vblank(dev, pipe)) + intel_check_page_flip(dev, pipe); if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) { intel_prepare_page_flip(dev, pipe); @@ -2768,7 +2785,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) if (eir & I915_ERROR_MEMORY_REFRESH) { pr_err("memory refresh error:\n"); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) pr_err("pipe %c stat: 0x%08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); /* pipestat has already been acked */ @@ -2865,52 +2882,6 @@ void i915_handle_error(struct drm_device *dev, bool wedged, schedule_work(&dev_priv->gpu_error.work); } -static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_i915_gem_object *obj; - struct intel_unpin_work *work; - unsigned long flags; - bool stall_detected; - - /* Ignore early vblank irqs */ - if (intel_crtc == NULL) - return; - - spin_lock_irqsave(&dev->event_lock, flags); - work = intel_crtc->unpin_work; - - if (work == NULL || - atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE || - !work->enable_stall_check) { - /* Either the pending flip IRQ arrived, or we're too early. Don't check */ - spin_unlock_irqrestore(&dev->event_lock, flags); - return; - } - - /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ - obj = work->pending_flip_obj; - if (INTEL_INFO(dev)->gen >= 4) { - int dspsurf = DSPSURF(intel_crtc->plane); - stall_detected = I915_HI_DISPBASE(I915_READ(dspsurf)) == - i915_gem_obj_ggtt_offset(obj); - } else { - int dspaddr = DSPADDR(intel_crtc->plane); - stall_detected = I915_READ(dspaddr) == (i915_gem_obj_ggtt_offset(obj) + - crtc->y * crtc->primary->fb->pitches[0] + - crtc->x * crtc->primary->fb->bits_per_pixel/8); - } - - spin_unlock_irqrestore(&dev->event_lock, flags); - - if (stall_detected) { - DRM_DEBUG_DRIVER("Pageflip stall detected\n"); - intel_prepare_page_flip(dev, intel_crtc->plane); - } -} - /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ @@ -3446,7 +3417,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev) I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IIR, 0xffffffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -3472,7 +3443,7 @@ static void gen8_irq_reset(struct drm_device *dev) gen8_gt_irq_reset(dev_priv); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); @@ -3487,12 +3458,13 @@ static void gen8_irq_reset(struct drm_device *dev) void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv) { unsigned long irqflags; + uint32_t extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_B, dev_priv->de_irq_mask[PIPE_B], - ~dev_priv->de_irq_mask[PIPE_B]); + ~dev_priv->de_irq_mask[PIPE_B] | extra_ier); GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_C, dev_priv->de_irq_mask[PIPE_C], - ~dev_priv->de_irq_mask[PIPE_C]); + ~dev_priv->de_irq_mask[PIPE_C] | extra_ier); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -3515,7 +3487,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev) I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -3527,18 +3499,17 @@ static void cherryview_irq_preinstall(struct drm_device *dev) static void ibx_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *intel_encoder; u32 hotplug_irqs, hotplug, enabled_irqs = 0; if (HAS_PCH_IBX(dev)) { hotplug_irqs = SDE_HOTPLUG_MASK; - list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) + for_each_intel_encoder(dev, intel_encoder) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin]; } else { hotplug_irqs = SDE_HOTPLUG_MASK_CPT; - list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) + for_each_intel_encoder(dev, intel_encoder) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) enabled_irqs |= hpd_cpt[intel_encoder->hpd_pin]; } @@ -3787,28 +3758,31 @@ static int valleyview_irq_postinstall(struct drm_device *dev) static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) { - int i; - /* These are interrupts we'll toggle with the ring mask register */ uint32_t gt_interrupts[] = { GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | + GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | GT_RENDER_L3_PARITY_ERROR_INTERRUPT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT, + GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT | + GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT, GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT, + GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | + GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT | + GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT, 0, - GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT + GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT | + GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT }; - for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) - GEN8_IRQ_INIT_NDX(GT, i, ~gt_interrupts[i], gt_interrupts[i]); - dev_priv->pm_irq_mask = 0xffffffff; + 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(GT, 2, dev_priv->pm_irq_mask, dev_priv->pm_rps_events); + GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); } static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; uint32_t de_pipe_masked = GEN8_PIPE_PRIMARY_FLIP_DONE | GEN8_PIPE_CDCLK_CRC_DONE | GEN8_DE_PIPE_IRQ_FAULT_ERRORS; @@ -3819,7 +3793,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked; dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, @@ -3864,12 +3838,12 @@ static int cherryview_irq_postinstall(struct drm_device *dev) */ dev_priv->irq_mask = ~enable_mask; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) i915_enable_pipestat(dev_priv, pipe, pipestat_enable); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); @@ -3892,8 +3866,6 @@ static void gen8_irq_uninstall(struct drm_device *dev) if (!dev_priv) return; - intel_hpd_irq_uninstall(dev_priv); - gen8_irq_reset(dev); } @@ -3908,9 +3880,7 @@ static void valleyview_irq_uninstall(struct drm_device *dev) I915_WRITE(VLV_MASTER_IER, 0); - intel_hpd_irq_uninstall(dev_priv); - - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(HWSTAM, 0xffffffff); @@ -3972,7 +3942,7 @@ do { \ I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -3988,8 +3958,6 @@ static void ironlake_irq_uninstall(struct drm_device *dev) if (!dev_priv) return; - intel_hpd_irq_uninstall(dev_priv); - ironlake_irq_reset(dev); } @@ -3998,7 +3966,7 @@ static void i8xx_irq_preinstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE16(IMR, 0xffff); I915_WRITE16(IER, 0x0); @@ -4052,7 +4020,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev, return false; if ((iir & flip_pending) == 0) - return false; + goto check_page_flip; intel_prepare_page_flip(dev, plane); @@ -4063,11 +4031,14 @@ static bool i8xx_handle_vblank(struct drm_device *dev, * an interrupt per se, we watch for the change at vblank. */ if (I915_READ16(ISR) & flip_pending) - return false; + goto check_page_flip; intel_finish_page_flip(dev, pipe); - return true; + +check_page_flip: + intel_check_page_flip(dev, pipe); + return false; } static irqreturn_t i8xx_irq_handler(int irq, void *arg) @@ -4098,7 +4069,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4118,7 +4089,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int plane = pipe; if (HAS_FBC(dev)) plane = !plane; @@ -4146,7 +4117,7 @@ static void i8xx_irq_uninstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { /* Clear enable bits; then clear status bits */ I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); @@ -4167,7 +4138,7 @@ static void i915_irq_preinstall(struct drm_device * dev) } I915_WRITE16(HWSTAM, 0xeffe); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); @@ -4237,7 +4208,7 @@ static bool i915_handle_vblank(struct drm_device *dev, return false; if ((iir & flip_pending) == 0) - return false; + goto check_page_flip; intel_prepare_page_flip(dev, plane); @@ -4248,11 +4219,14 @@ static bool i915_handle_vblank(struct drm_device *dev, * an interrupt per se, we watch for the change at vblank. */ if (I915_READ(ISR) & flip_pending) - return false; + goto check_page_flip; intel_finish_page_flip(dev, pipe); - return true; + +check_page_flip: + intel_check_page_flip(dev, pipe); + return false; } static irqreturn_t i915_irq_handler(int irq, void *arg) @@ -4282,7 +4256,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4308,7 +4282,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int plane = pipe; if (HAS_FBC(dev)) plane = !plane; @@ -4360,15 +4334,13 @@ static void i915_irq_uninstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - intel_hpd_irq_uninstall(dev_priv); - if (I915_HAS_HOTPLUG(dev)) { I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } I915_WRITE16(HWSTAM, 0xffff); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { /* Clear enable bits; then clear status bits */ I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); @@ -4388,7 +4360,7 @@ static void i965_irq_preinstall(struct drm_device * dev) I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xeffe); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); @@ -4457,7 +4429,6 @@ static int i965_irq_postinstall(struct drm_device *dev) static void i915_hpd_irq_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *intel_encoder; u32 hotplug_en; @@ -4468,7 +4439,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev) hotplug_en &= ~HOTPLUG_INT_EN_MASK; /* Note HDMI and DP share hotplug bits */ /* enable bits are the same for all generations */ - list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) + for_each_intel_encoder(dev, intel_encoder) if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED) hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin]; /* Programming the CRT detection parameters tends @@ -4514,7 +4485,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4545,7 +4516,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (iir & I915_BSD_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && i915_handle_vblank(dev, pipe, pipe, iir)) flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); @@ -4598,31 +4569,33 @@ static void i965_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - intel_hpd_irq_uninstall(dev_priv); - I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xffffffff); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); } -static void intel_hpd_irq_reenable(unsigned long data) +static void intel_hpd_irq_reenable(struct work_struct *work) { - struct drm_i915_private *dev_priv = (struct drm_i915_private *)data; + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), + hotplug_reenable_work.work); struct drm_device *dev = dev_priv->dev; struct drm_mode_config *mode_config = &dev->mode_config; unsigned long irqflags; int i; + intel_runtime_pm_get(dev_priv); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) { struct drm_connector *connector; @@ -4648,6 +4621,8 @@ static void intel_hpd_irq_reenable(unsigned long data) if (dev_priv->display.hpd_irq_setup) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + + intel_runtime_pm_put(dev_priv); } void intel_irq_init(struct drm_device *dev) @@ -4661,8 +4636,8 @@ void intel_irq_init(struct drm_device *dev) INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); /* Let's track the enabled rps events */ - if (IS_VALLEYVIEW(dev)) - /* WaGsvRC0ResidenncyMethod:VLV */ + if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) + /* WaGsvRC0ResidencyMethod:vlv */ dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; else dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; @@ -4670,8 +4645,8 @@ void intel_irq_init(struct drm_device *dev) setup_timer(&dev_priv->gpu_error.hangcheck_timer, i915_hangcheck_elapsed, (unsigned long) dev); - setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable, - (unsigned long) dev_priv); + INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work, + intel_hpd_irq_reenable); pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); @@ -4689,6 +4664,14 @@ void intel_irq_init(struct drm_device *dev) dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ } + /* + * Opt out of the vblank disable timer on everything except gen2. + * Gen2 doesn't have a hardware frame counter and so depends on + * vblank interrupts to produce sane vblank seuquence numbers. + */ + if (!IS_GEN2(dev)) + dev->vblank_disable_immediate = true; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; |