[Intel-gfx] [PATCH 3/6] drm/i915: Disable render idle on user forcewake

Mika Kuoppala mika.kuoppala at linux.intel.com
Thu Sep 18 16:58:32 CEST 2014


Render context on gen8 is not guaranteed to be loaded (active)
at the instant when forcewake ack shows up. So we need extra
steps to get it in before we access specific registers.

We could do register white listing to do the extra dance only on
specific render context access. However the main concern is
is ring initialization after reset/resume, so only take the extra
steps on user forcewake as it is already guarding ring init. And not incur
extra perf penalty to regular register accesses. This allows us to be
sure that we don't read all zeros on RMW cycles. And we to show a
consistent state to igt when user fw has been acquired.

Based on earlier work by Ville Syrjälä <ville.syrjala at linux.intel.com>

Signed-off-by: Mika Kuoppala <mika.kuoppala at intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |  4 ++++
 drivers/gpu/drm/i915/i915_reg.h         |  4 ++++
 drivers/gpu/drm/i915/intel_ringbuffer.c |  4 ++++
 drivers/gpu/drm/i915/intel_uncore.c     | 37 ++++++++++++++++++++++++++++++---
 4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a03361c..89b740b 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2655,6 +2655,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
 
 	intel_runtime_pm_get(dev_priv);
 
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
 	seq_printf(m, "Workarounds applied: %d\n", dev_priv->num_wa_regs);
 	for (i = 0; i < dev_priv->num_wa_regs; ++i) {
 		u32 addr, mask;
@@ -2669,6 +2671,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
 				   dev_priv->intel_wa_regs[i].mask);
 	}
 
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+
 	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ad8179b..b98138d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1401,9 +1401,13 @@ enum punit_power_well {
 #define   GEN6_BLITTER_FBC_NOTIFY			(1<<3)
 
 #define GEN6_RC_SLEEP_PSMI_CONTROL	0x2050
+#define   GEN6_RC_SLEEP_MSG_DISABLE	(1 << 0)
 #define   GEN8_RC_SEMA_IDLE_MSG_DISABLE	(1 << 12)
 #define   GEN8_FF_DOP_CLOCK_GATE_DISABLE	(1<<10)
 
+#define GEN6_CSPWRFSM			0x22ac
+#define   GEN6_CSPWRFSM_CS_NONIDLE	(0x3 << 4)
+
 #define GEN6_BSD_SLEEP_PSMI_CONTROL	0x12050
 #define   GEN6_BSD_SLEEP_MSG_DISABLE	(1 << 0)
 #define   GEN6_BSD_SLEEP_FLUSH_DISABLE	(1 << 2)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 922d6bc..46cd0f9 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -813,6 +813,8 @@ static int init_render_ring(struct intel_engine_cs *ring)
 	if (ret)
 		return ret;
 
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
 	if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7)
 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
@@ -860,6 +862,8 @@ static int init_render_ring(struct intel_engine_cs *ring)
 	if (HAS_L3_DPF(dev))
 		I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
 
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 918b761..08587bd 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -299,6 +299,30 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static void __render_wake_get(struct drm_i915_private *dev_priv)
+{
+	if (INTEL_INFO(dev_priv->dev)->gen != 8)
+		return;
+
+	__raw_i915_write32(dev_priv, GEN6_RC_SLEEP_PSMI_CONTROL,
+			   _MASKED_BIT_ENABLE(GEN6_RC_SLEEP_MSG_DISABLE));
+
+	if (wait_for_atomic_us((__raw_i915_read32(dev_priv, GEN6_CSPWRFSM)
+				 & GEN6_CSPWRFSM_CS_NONIDLE)
+			       == GEN6_CSPWRFSM_CS_NONIDLE,
+			       500))
+		DRM_ERROR("Render wake get timed out\n");
+}
+
+static void __render_wake_put(struct drm_i915_private *dev_priv)
+{
+	if (INTEL_INFO(dev_priv->dev)->gen != 8)
+		return;
+
+	__raw_i915_write32(dev_priv, GEN6_RC_SLEEP_PSMI_CONTROL,
+			   _MASKED_BIT_DISABLE(GEN6_RC_SLEEP_MSG_DISABLE));
+}
+
 static void gen6_force_wake_timer(unsigned long arg)
 {
 	struct drm_i915_private *dev_priv = (void *)arg;
@@ -309,8 +333,11 @@ static void gen6_force_wake_timer(unsigned long arg)
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 	WARN_ON(!dev_priv->uncore.forcewake_count);
 
-	if (--dev_priv->uncore.forcewake_count == 0)
+	if (--dev_priv->uncore.forcewake_count == 0) {
+		__render_wake_put(dev_priv);
 		dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
+	}
+
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
 	intel_runtime_pm_put(dev_priv);
@@ -351,8 +378,10 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
 				fw = FORCEWAKE_ALL;
 		}
 
-		if (fw)
+		if (fw) {
 			dev_priv->uncore.funcs.force_wake_get(dev_priv, fw);
+			__render_wake_get(dev_priv);
+		}
 
 		if (IS_GEN6(dev) || IS_GEN7(dev))
 			dev_priv->uncore.fifo_count =
@@ -415,8 +444,10 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 		return vlv_force_wake_get(dev_priv, fw_engine);
 
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-	if (dev_priv->uncore.forcewake_count++ == 0)
+	if (dev_priv->uncore.forcewake_count++ == 0) {
 		dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
+		__render_wake_get(dev_priv);
+	}
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-- 
1.9.1




More information about the Intel-gfx mailing list