drm/i915: Abstract the legacy workload submission mechanism away
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_irq.c
index 3ae33e7e9d0965e11c862b1a60767f2c0dc7e3f1..f0d24db76e72fdc2b8b12d57fea8dc83c5d87ec4 100644 (file)
@@ -136,7 +136,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (WARN_ON(dev_priv->pm.irqs_disabled))
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        if ((dev_priv->irq_mask & mask) != 0) {
@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (dev_priv->pm.irqs_disabled)
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        if ((dev_priv->irq_mask & mask) != mask) {
@@ -173,7 +173,7 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
 {
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (WARN_ON(dev_priv->pm.irqs_disabled))
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        dev_priv->gt_irq_mask &= ~interrupt_mask;
@@ -206,7 +206,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (WARN_ON(dev_priv->pm.irqs_disabled))
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        new_val = dev_priv->pm_irq_mask;
@@ -264,7 +264,7 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (WARN_ON(dev_priv->pm.irqs_disabled))
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        new_val = dev_priv->pm_irq_mask;
@@ -420,7 +420,7 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (WARN_ON(dev_priv->pm.irqs_disabled))
+       if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
        I915_WRITE(SDEIMR, sdeimr);
@@ -1156,10 +1156,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
        bool changed = false;
        u32 hpd_event_bits;
 
-       /* HPD irq before everything is fully set up. */
-       if (!dev_priv->enable_hotplug_processing)
-               return;
-
        mutex_lock(&mode_config->mutex);
        DRM_DEBUG_KMS("running encoder hotplug functions\n");
 
@@ -1169,6 +1165,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
        dev_priv->hpd_event_bits = 0;
        list_for_each_entry(connector, &mode_config->connector_list, head) {
                intel_connector = to_intel_connector(connector);
+               if (!intel_connector->encoder)
+                       continue;
                intel_encoder = intel_connector->encoder;
                if (intel_encoder->hpd_pin > HPD_NONE &&
                    dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
@@ -1199,6 +1197,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
 
        list_for_each_entry(connector, &mode_config->connector_list, head) {
                intel_connector = to_intel_connector(connector);
+               if (!intel_connector->encoder)
+                       continue;
                intel_encoder = intel_connector->encoder;
                if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
                        if (intel_encoder->hot_plug)
@@ -1327,10 +1327,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++;
 
@@ -1846,7 +1846,7 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
         * deadlock.
         */
        if (queue_dig)
-               schedule_work(&dev_priv->dig_port_work);
+               queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
        if (queue_hp)
                schedule_work(&dev_priv->hotplug_work);
 }
@@ -1989,14 +1989,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;
 }
 
@@ -3150,7 +3145,7 @@ static int semaphore_passed(struct intel_engine_cs *ring)
 {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct intel_engine_cs *signaller;
-       u32 seqno, ctl;
+       u32 seqno;
 
        ring->hangcheck.deadlock++;
 
@@ -3162,15 +3157,12 @@ static int semaphore_passed(struct intel_engine_cs *ring)
        if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
                return -1;
 
-       /* cursory check for an unkickable deadlock */
-       ctl = I915_READ_CTL(signaller);
-       if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
-               return -1;
-
        if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
                return 1;
 
-       if (signaller->hangcheck.deadlock)
+       /* cursory check for an unkickable deadlock */
+       if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
+           semaphore_passed(signaller) < 0)
                return -1;
 
        return 0;
@@ -3192,8 +3184,14 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 tmp;
 
-       if (ring->hangcheck.acthd != acthd)
-               return HANGCHECK_ACTIVE;
+       if (acthd != ring->hangcheck.acthd) {
+               if (acthd > ring->hangcheck.max_acthd) {
+                       ring->hangcheck.max_acthd = acthd;
+                       return HANGCHECK_ACTIVE;
+               }
+
+               return HANGCHECK_ACTIVE_LOOP;
+       }
 
        if (IS_GEN2(dev))
                return HANGCHECK_HUNG;
@@ -3304,8 +3302,9 @@ static void i915_hangcheck_elapsed(unsigned long data)
                                switch (ring->hangcheck.action) {
                                case HANGCHECK_IDLE:
                                case HANGCHECK_WAIT:
-                                       break;
                                case HANGCHECK_ACTIVE:
+                                       break;
+                               case HANGCHECK_ACTIVE_LOOP:
                                        ring->hangcheck.score += BUSY;
                                        break;
                                case HANGCHECK_KICK:
@@ -3325,6 +3324,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
                         */
                        if (ring->hangcheck.score > 0)
                                ring->hangcheck.score--;
+
+                       ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
                }
 
                ring->hangcheck.seqno = seqno;
@@ -3521,18 +3522,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];
        }
@@ -4451,7 +4451,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;
 
@@ -4462,7 +4461,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
@@ -4669,6 +4668,9 @@ void intel_irq_init(struct drm_device *dev)
 
        pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 
+       /* Haven't installed the IRQ handler yet */
+       dev_priv->pm._irqs_disabled = true;
+
        if (IS_GEN2(dev)) {
                dev->max_vblank_count = 0;
                dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
@@ -4756,7 +4758,9 @@ void intel_hpd_init(struct drm_device *dev)
        list_for_each_entry(connector, &mode_config->connector_list, head) {
                struct intel_connector *intel_connector = to_intel_connector(connector);
                connector->polled = intel_connector->polled;
-               if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+               if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+                       connector->polled = DRM_CONNECTOR_POLL_HPD;
+               if (intel_connector->mst_port)
                        connector->polled = DRM_CONNECTOR_POLL_HPD;
        }
 
@@ -4774,7 +4778,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        dev->driver->irq_uninstall(dev);
-       dev_priv->pm.irqs_disabled = true;
+       dev_priv->pm._irqs_disabled = true;
 }
 
 /* Restore interrupts so we can recover from runtime PM. */
@@ -4782,7 +4786,7 @@ void intel_runtime_pm_restore_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       dev_priv->pm.irqs_disabled = false;
+       dev_priv->pm._irqs_disabled = false;
        dev->driver->irq_preinstall(dev);
        dev->driver->irq_postinstall(dev);
 }
This page took 0.029914 seconds and 5 git commands to generate.