drm/i915: Include instdone[1] in hangcheck
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / i915_irq.c
index 70e1e4b..85785a8 100644 (file)
@@ -171,10 +171,10 @@ void intel_enable_asle (struct drm_device *dev)
                ironlake_enable_display_irq(dev_priv, DE_GSE);
        else {
                i915_enable_pipestat(dev_priv, 1,
-                                    I915_LEGACY_BLC_EVENT_ENABLE);
+                                    PIPE_LEGACY_BLC_EVENT_ENABLE);
                if (IS_I965G(dev))
                        i915_enable_pipestat(dev_priv, 0,
-                                            I915_LEGACY_BLC_EVENT_ENABLE);
+                                            PIPE_LEGACY_BLC_EVENT_ENABLE);
        }
 }
 
@@ -842,7 +842,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
        u32 iir, new_iir;
        u32 pipea_stats, pipeb_stats;
        u32 vblank_status;
-       u32 vblank_enable;
        int vblank = 0;
        unsigned long irqflags;
        int irq_received;
@@ -856,13 +855,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 
        iir = I915_READ(IIR);
 
-       if (IS_I965G(dev)) {
-               vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
-               vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
-       } else {
-               vblank_status = I915_VBLANK_INTERRUPT_STATUS;
-               vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
-       }
+       if (IS_I965G(dev))
+               vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
+       else
+               vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
 
        for (;;) {
                irq_received = iir != 0;
@@ -947,9 +943,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                }
 
                if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+                       intel_prepare_page_flip(dev, 1);
                        if (dev_priv->flip_pending_is_done)
                                intel_finish_page_flip_plane(dev, 1);
-                       intel_prepare_page_flip(dev, 1);
                }
 
                if (pipea_stats & vblank_status) {
@@ -966,8 +962,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                                intel_finish_page_flip(dev, 1);
                }
 
-               if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
-                   (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
+               if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
+                   (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
                    (iir & I915_ASLE_INTERRUPT))
                        opregion_asle_intr(dev);
 
@@ -1233,16 +1229,21 @@ void i915_hangcheck_elapsed(unsigned long data)
 {
        struct drm_device *dev = (struct drm_device *)data;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t acthd;
+       uint32_t acthd, instdone, instdone1;
 
        /* No reset support on this chip yet. */
        if (IS_GEN6(dev))
                return;
 
-       if (!IS_I965G(dev))
+       if (!IS_I965G(dev)) {
                acthd = I915_READ(ACTHD);
-       else
+               instdone = I915_READ(INSTDONE);
+               instdone1 = 0;
+       } else {
                acthd = I915_READ(ACTHD_I965);
+               instdone = I915_READ(INSTDONE_I965);
+               instdone1 = I915_READ(INSTDONE1);
+       }
 
        /* If all work is done then ACTHD clearly hasn't advanced. */
        if (list_empty(&dev_priv->render_ring.request_list) ||
@@ -1253,21 +1254,24 @@ void i915_hangcheck_elapsed(unsigned long data)
                return;
        }
 
-       if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) {
-               DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
-               i915_handle_error(dev, true);
-               return;
-       } 
+       if (dev_priv->last_acthd == acthd &&
+           dev_priv->last_instdone == instdone &&
+           dev_priv->last_instdone1 == instdone1) {
+               if (dev_priv->hangcheck_count++ > 1) {
+                       DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
+                       i915_handle_error(dev, true);
+                       return;
+               }
+       } else {
+               dev_priv->hangcheck_count = 0;
+
+               dev_priv->last_acthd = acthd;
+               dev_priv->last_instdone = instdone;
+               dev_priv->last_instdone1 = instdone1;
+       }
 
        /* Reset timer case chip hangs without another request being added */
        mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
-
-       if (acthd != dev_priv->last_acthd)
-               dev_priv->hangcheck_count = 0;
-       else
-               dev_priv->hangcheck_count++;
-
-       dev_priv->last_acthd = acthd;
 }
 
 /* drm_dma.h hooks
@@ -1434,8 +1438,18 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
                        hotplug_en |= SDVOC_HOTPLUG_INT_EN;
                if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
                        hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
                        hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+                       /* 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_50;
+               }
+
                /* Ignore TV since it's buggy */
 
                I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);