X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fi915_irq.c;h=2399eaed2ca370f6cc276ce28f50adefb59f9f7d;hb=2545e4a6c8f5ae819635403390d940b595c26241;hp=d0d3dfbe6d2adae46d968f8112675276197f15c6;hpb=a30e93186c607684ed2d8283c95d30c7f1007aa3;p=deliverable%2Flinux.git diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d0d3dfbe6d2a..2399eaed2ca3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -45,7 +45,7 @@ * and related files, but that will be described in separate chapters. */ -static const u32 hpd_ibx[] = { +static const u32 hpd_ibx[HPD_NUM_PINS] = { [HPD_CRT] = SDE_CRT_HOTPLUG, [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, [HPD_PORT_B] = SDE_PORTB_HOTPLUG, @@ -53,7 +53,7 @@ static const u32 hpd_ibx[] = { [HPD_PORT_D] = SDE_PORTD_HOTPLUG }; -static const u32 hpd_cpt[] = { +static const u32 hpd_cpt[HPD_NUM_PINS] = { [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, @@ -61,7 +61,7 @@ static const u32 hpd_cpt[] = { [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT }; -static const u32 hpd_mask_i915[] = { +static const u32 hpd_mask_i915[HPD_NUM_PINS] = { [HPD_CRT] = CRT_HOTPLUG_INT_EN, [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, @@ -70,7 +70,7 @@ static const u32 hpd_mask_i915[] = { [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN }; -static const u32 hpd_status_g4x[] = { +static const u32 hpd_status_g4x[HPD_NUM_PINS] = { [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, @@ -79,7 +79,7 @@ static const u32 hpd_status_g4x[] = { [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS }; -static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */ +static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are the same */ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, @@ -183,6 +183,8 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, { assert_spin_locked(&dev_priv->irq_lock); + WARN_ON(enabled_irq_mask & ~interrupt_mask); + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; @@ -229,6 +231,8 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, { uint32_t new_val; + WARN_ON(enabled_irq_mask & ~interrupt_mask); + assert_spin_locked(&dev_priv->irq_lock); new_val = dev_priv->pm_irq_mask; @@ -292,6 +296,23 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) spin_unlock_irq(&dev_priv->irq_lock); } +u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) +{ + /* + * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer + * if GEN6_PM_UP_EI_EXPIRED is masked. + * + * TODO: verify if this can be reproduced on VLV,CHV. + */ + if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv)) + mask &= ~GEN6_PM_RP_UP_EI_EXPIRED; + + if (INTEL_INFO(dev_priv)->gen >= 8) + mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP; + + return mask; +} + void gen6_disable_rps_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -304,8 +325,7 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) spin_lock_irq(&dev_priv->irq_lock); - I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ? - ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0); + I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & @@ -332,6 +352,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, sdeimr &= ~interrupt_mask; sdeimr |= (~enabled_irq_mask & interrupt_mask); + WARN_ON(enabled_irq_mask & ~interrupt_mask); + assert_spin_locked(&dev_priv->irq_lock); if (WARN_ON(!intel_irqs_enabled(dev_priv))) @@ -571,7 +593,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) struct intel_crtc *intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); const struct drm_display_mode *mode = - &intel_crtc->config.adjusted_mode; + &intel_crtc->config->base.adjusted_mode; htotal = mode->crtc_htotal; hsync_start = mode->crtc_hsync_start; @@ -642,7 +664,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - const struct drm_display_mode *mode = &crtc->config.adjusted_mode; + const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode; enum pipe pipe = crtc->pipe; int position, vtotal; @@ -669,7 +691,7 @@ static int i915_get_crtc_scanoutpos(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); - const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode; + const struct drm_display_mode *mode = &intel_crtc->config->base.adjusted_mode; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; @@ -827,7 +849,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, vblank_time, flags, crtc, - &to_intel_crtc(crtc)->config.adjusted_mode); + &to_intel_crtc(crtc)->config->base.adjusted_mode); } static bool intel_hpd_irq_event(struct drm_device *dev, @@ -857,7 +879,7 @@ static void i915_digport_work_func(struct work_struct *work) container_of(work, struct drm_i915_private, dig_port_work); u32 long_port_mask, short_port_mask; struct intel_digital_port *intel_dig_port; - int i, ret; + int i; u32 old_bits = 0; spin_lock_irq(&dev_priv->irq_lock); @@ -881,9 +903,11 @@ static void i915_digport_work_func(struct work_struct *work) valid = true; if (valid) { + enum irqreturn ret; + ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd); - if (ret == true) { - /* if we get true fallback to old school hpd */ + if (ret == IRQ_NONE) { + /* fall back to old school hpd */ old_bits |= (1 << intel_dig_port->base.hpd_pin); } } @@ -1017,7 +1041,7 @@ static void notify_ring(struct drm_device *dev, if (!intel_ring_initialized(ring)) return; - trace_i915_gem_request_complete(ring); + trace_i915_gem_request_notify(ring); wake_up_all(&ring->irq_queue); } @@ -1383,14 +1407,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (rcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); bcs = tmp >> GEN8_BCS_IRQ_SHIFT; ring = &dev_priv->ring[BCS]; if (bcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } @@ -1406,14 +1430,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; ring = &dev_priv->ring[VCS2]; if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } @@ -1440,7 +1464,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } @@ -1500,7 +1524,7 @@ static inline enum port get_port_from_pin(enum hpd_pin pin) static inline void intel_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, u32 dig_hotplug_reg, - const u32 *hpd) + const u32 hpd[HPD_NUM_PINS]) { struct drm_i915_private *dev_priv = dev->dev_private; int i; @@ -2753,18 +2777,18 @@ static void gen8_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static u32 -ring_last_seqno(struct intel_engine_cs *ring) +static struct drm_i915_gem_request * +ring_last_request(struct intel_engine_cs *ring) { return list_entry(ring->request_list.prev, - struct drm_i915_gem_request, list)->seqno; + struct drm_i915_gem_request, list); } static bool -ring_idle(struct intel_engine_cs *ring, u32 seqno) +ring_idle(struct intel_engine_cs *ring) { return (list_empty(&ring->request_list) || - i915_seqno_passed(seqno, ring_last_seqno(ring))); + i915_gem_request_completed(ring_last_request(ring), false)); } static bool @@ -2984,7 +3008,7 @@ static void i915_hangcheck_elapsed(unsigned long data) acthd = intel_ring_get_active_head(ring); if (ring->hangcheck.seqno == seqno) { - if (ring_idle(ring, seqno)) { + if (ring_idle(ring)) { ring->hangcheck.action = HANGCHECK_IDLE; if (waitqueue_active(&ring->irq_queue)) { @@ -4123,26 +4147,24 @@ static void i915_hpd_irq_setup(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - if (I915_HAS_HOTPLUG(dev)) { - hotplug_en = I915_READ(PORT_HOTPLUG_EN); - hotplug_en &= ~HOTPLUG_INT_EN_MASK; - /* Note HDMI and DP share hotplug bits */ - /* enable bits are the same for all generations */ - 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 - to generate a spurious hotplug event about three - seconds later. So just do it once. - */ - if (IS_G4X(dev)) - hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK; - hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - - /* Ignore TV since it's buggy */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - } + hotplug_en = I915_READ(PORT_HOTPLUG_EN); + hotplug_en &= ~HOTPLUG_INT_EN_MASK; + /* Note HDMI and DP share hotplug bits */ + /* enable bits are the same for all generations */ + 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 + to generate a spurious hotplug event about three + seconds later. So just do it once. + */ + if (IS_G4X(dev)) + hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; + hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK; + hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; + + /* Ignore TV since it's buggy */ + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); } static irqreturn_t i965_irq_handler(int irq, void *arg) @@ -4406,14 +4428,14 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_postinstall = i915_irq_postinstall; dev->driver->irq_uninstall = i915_irq_uninstall; dev->driver->irq_handler = i915_irq_handler; - dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } else { dev->driver->irq_preinstall = i965_irq_preinstall; dev->driver->irq_postinstall = i965_irq_postinstall; dev->driver->irq_uninstall = i965_irq_uninstall; dev->driver->irq_handler = i965_irq_handler; - dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } + if (I915_HAS_HOTPLUG(dev_priv)) + dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; dev->driver->enable_vblank = i915_enable_vblank; dev->driver->disable_vblank = i915_disable_vblank; }