[Intel-gfx] [PATCH 2/4] drm/i915: fix rc6 initialization on Ironlake

Ben Widawsky ben at bwidawsk.net
Sat Mar 19 00:12:46 CET 2011


There is a race condition between setting PWRCTXA and executing
MI_SET_CONTEXT. PWRCTXA must not be set until a valid context has been
written (or else the GPU could possible go into rc6, and return to an
invalid context).

Reported-and-Tested-by: Gu Rui <chaos.proton at gmail.com>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28582
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_display.c |   32 +++++++++++++++++++++++++++++---
 1 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 790af25..c1e9c30 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6603,14 +6603,27 @@ static int ironlake_setup_rc6(struct drm_device *dev)
 	return 0;
 }
 
+static int ironlake_wait_set_context(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = LP_RING(dev_priv);
+	int ret = -EAGAIN;
+
+	ret = wait_for((I915_READ_HEAD(ring) == I915_READ_TAIL(ring)), 1000);
+	if (ret && atomic_read(&dev_priv->mm.wedged)) {
+		ret = -EIO;
+	} else if (!ret) { /* head == tail */
+		ret = 0;
+	}
+
+	return ret;
+}
+
 void ironlake_enable_rc6(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	/* rc6 disabled by default due to repeated reports of hanging during
-	 * boot and resume.
-	 */
 	if (!i915_enable_rc6)
 		return;
 
@@ -6640,6 +6653,19 @@ void ironlake_enable_rc6(struct drm_device *dev)
 	OUT_RING(MI_FLUSH);
 	ADVANCE_LP_RING();
 
+	/*
+	 * Wait for the command parser to advance past MI_SET_CONTEXT. The HW
+	 * does an implicit flush, combined with MI_FLUSH above, it should be
+	 * safe to assume that renderctx is valid
+	 */
+	ret = ironlake_wait_set_context(dev);
+	if (ret) {
+		if (ret == -EAGAIN)
+			DRM_ERROR("rc6 switch took too long, freeing the bo");
+		ironlake_teardown_rc6(dev, true);
+		return;
+	}
+
 	I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
 	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
 }
-- 
1.7.3.4




More information about the Intel-gfx mailing list