drm/i915: Hold gt_lock during reset
authorKeith Packard <keithp@keithp.com>
Fri, 6 Jan 2012 19:44:11 +0000 (11:44 -0800)
committerKeith Packard <keithp@keithp.com>
Thu, 19 Jan 2012 20:28:42 +0000 (12:28 -0800)
This ensures that no register reads occur while the forcewake state of
the hardware is indeterminate during the reset operation.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c

index a6fcd941e3ab60828e825cb2e16069923929ef7c..062d1d27f704231e3334d21e1316bc63fbe27a2f 100644 (file)
@@ -603,12 +603,31 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
        int     ret;
        unsigned long irqflags;
 
-       I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
-       ret = wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
-       /* If reset with a user forcewake, try to restore */
+       /* Hold gt_lock across reset to prevent any register access
+        * with forcewake not set correctly
+        */
        spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+
+       /* Reset the chip */
+
+       /* GEN6_GDRST is not in the gt power well, no need to check
+        * for fifo space for the write or forcewake the chip for
+        * the read
+        */
+       I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
+
+       /* Spin waiting for the device to ack the reset request */
+       ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+       /* If reset with a user forcewake, try to restore, otherwise turn it off */
        if (dev_priv->forcewake_count)
                dev_priv->display.force_wake_get(dev_priv);
+       else
+               dev_priv->display.force_wake_put(dev_priv);
+
+       /* Restore fifo count */
+       dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+
        spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
        return ret;
 }