[PATCH 65/65] drm/i915: Enable rc6 for Ironlake

Chris Wilson chris at chris-wilson.co.uk
Fri Jan 19 09:15:15 UTC 2018


Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  16 ++++--
 drivers/gpu/drm/i915/i915_drv.h     |   2 +
 drivers/gpu/drm/i915/i915_pci.c     |   3 +-
 drivers/gpu/drm/i915/intel_gt_pm.c  | 101 ++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e4ae35df1322..0e6d11138459 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1354,12 +1354,13 @@ static int i915_reset_info(struct seq_file *m, void *unused)
 static int ironlake_drpc_info(struct seq_file *m)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
-	u32 rgvmodectl, rstdbyctl;
+	u32 rgvmodectl, rstdbyctl, pwrctx;
 	u16 crstandvid;
 
 	rgvmodectl = I915_READ(MEMMODECTL);
 	rstdbyctl = I915_READ(RSTDBYCTL);
 	crstandvid = I915_READ16(CRSTANDVID);
+	pwrctx = I915_READ(PWRCTXA);
 
 	seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
 	seq_printf(m, "Boost freq: %d\n",
@@ -1379,12 +1380,15 @@ static int ironlake_drpc_info(struct seq_file *m)
 	seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
 	seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
 	seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
-	seq_printf(m, "Render standby enabled: %s\n",
-		   yesno(!(rstdbyctl & RCX_SW_EXIT)));
+	seq_printf(m, "Render standby: %08x\n", rstdbyctl);
+	seq_printf(m, "RS enabled: %s\n", yesno(!(rstdbyctl & RCX_SW_EXIT)));
+	seq_printf(m, "RS1/RC1 enabled? %s\n", yesno(rstdbyctl & RS1EN));
+	seq_printf(m, "RS2/RC6 enabled? %s\n", yesno(rstdbyctl & RS2EN));
+	seq_printf(m, "RS3/RC6+ enabled? %s\n", yesno(rstdbyctl & RS3EN));
 	seq_puts(m, "Current RS state: ");
 	switch (rstdbyctl & RSX_STATUS_MASK) {
 	case RSX_STATUS_ON:
-		seq_puts(m, "on\n");
+		seq_puts(m, "busy\n");
 		break;
 	case RSX_STATUS_RC1:
 		seq_puts(m, "RC1\n");
@@ -1399,12 +1403,14 @@ static int ironlake_drpc_info(struct seq_file *m)
 		seq_puts(m, "RS2 (RC6)\n");
 		break;
 	case RSX_STATUS_RS3:
-		seq_puts(m, "RC3 (RC6+)\n");
+		seq_puts(m, "RS3 (RC6+)\n");
 		break;
 	default:
 		seq_puts(m, "unknown\n");
 		break;
 	}
+	seq_printf(m, "Power context: %x, enabled? %s\n",
+		   pwrctx & ~PWRCTX_EN, yesno(pwrctx & PWRCTX_EN));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e30947457d7b..62a7f4e62b7c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -971,6 +971,8 @@ struct intel_gt_pm {
 	 * global mchdev_lock in intel_gt_pm.c
 	 * */
 	struct intel_ips ips;
+
+	struct i915_vma *pctx;
 };
 
 struct drm_i915_private;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 86aef877966a..a3d913837a22 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -209,8 +209,7 @@ static const struct intel_device_info intel_gm45_info __initconst = {
 	.has_hotplug = 1, \
 	.ring_mask = RENDER_RING | BSD_RING, \
 	.has_snoop = true, \
-	/* ilk does support rc6, but we do not implement [power] contexts */ \
-	.has_rc6 = 0, \
+	.has_rc6 = true, \
 	GEN_DEFAULT_PIPEOFFSETS, \
 	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.c b/drivers/gpu/drm/i915/intel_gt_pm.c
index 0c70d66ddaf3..cef00eaaa05e 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/intel_gt_pm.c
@@ -182,6 +182,30 @@ static void ironlake_disable_drps(struct drm_i915_private *dev_priv)
 	spin_unlock(&mchdev_lock);
 }
 
+static bool gen5_disable_rs(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
+	return intel_wait_for_register(dev_priv,
+				       RSTDBYCTL,
+				       RSX_STATUS_MASK, RSX_STATUS_ON,
+				       50) == 0;
+}
+
+static void gen5_enable_rs(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+}
+
+static void __gen5_enable_rc6(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RS2EN);
+}
+
+static void __gen5_disable_rc6(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RS2EN);
+}
+
 /* There's a funny hw issue where the hw returns all 0 when reading from
  * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value
  * ourselves, instead of doing a rmw cycle (which might result in us clearing
@@ -608,6 +632,7 @@ void intel_rps_busy(struct drm_i915_private *dev_priv)
 		memset(&rps->ei, 0, sizeof(rps->ei));
 		gen6_enable_rps_interrupts(dev_priv);
 	} else if (INTEL_GEN(dev_priv) >= 5) {
+		__gen5_disable_rc6(dev_priv);
 		gen5_update_gfx_val(dev_priv);
 	}
 }
@@ -654,6 +679,9 @@ void intel_rps_idle(struct drm_i915_private *dev_priv)
 	if (INTEL_GEN(dev_priv) >= 6) {
 		I915_WRITE(GEN6_PMINTRMSK,
 			   gen6_sanitize_rps_pm_mask(dev_priv, ~0));
+	} else if (INTEL_GEN(dev_priv) >= 5) {
+		gen5_update_gfx_val(dev_priv);
+		__gen5_enable_rc6(dev_priv);
 	}
 
 	rps->last_adj = 0;
@@ -727,6 +755,32 @@ static void gen9_disable_rps(struct drm_i915_private *dev_priv)
 	I915_WRITE(GEN6_RP_CONTROL, 0);
 }
 
+static void gen5_enable_rc6(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	gen5_disable_rs(dev_priv);
+
+	I915_WRITE(PWRCTXA, i915_ggtt_offset(dev_priv->gt_pm.pctx) | PWRCTX_EN);
+	POSTING_READ(PWRCTXA);
+
+	val = I915_READ(RSTDBYCTL);
+	val &= ~(RS3EN | D3RS3EN | RCX_SW_EXIT);
+	val |= RS2EN | RS1EN;
+	I915_WRITE(RSTDBYCTL, val);
+}
+
+static void gen5_disable_rc6(struct drm_i915_private *dev_priv)
+{
+	/* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
+	gen5_disable_rs(dev_priv);
+
+	I915_WRITE(PWRCTXA, 0);
+	POSTING_READ(PWRCTXA);
+
+	gen5_enable_rs(dev_priv);
+}
+
 static void gen6_disable_rc6(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -1546,11 +1600,52 @@ static void ilk_init_frequencies(struct drm_i915_private *i915)
 		ips->c_m = 2;
 }
 
+static unsigned long ilk_pctx_size(struct drm_i915_private *dev_priv)
+{
+	return (1 + ((I915_READ(PWRCTXA) >> 1) & 0xf)) << 12;
+}
+
 static void gen5_init_gt_powersave(struct drm_i915_private *i915)
 {
+	struct drm_i915_gem_object *obj;
+	struct i915_vma *vma;
+	void __iomem *map;
+	unsigned long sz;
+
 	ilk_init_frequencies(i915);
 	ilk_init_emon(i915);
 	ironlake_init_drps(i915);
+
+	sz = ilk_pctx_size(i915);
+
+	obj = i915_gem_object_create_stolen(i915, sz);
+	if (!obj)
+                obj = i915_gem_object_create_internal(i915, sz);
+	if (IS_ERR(obj))
+		goto err;
+
+	vma = i915_vma_instance(obj, &i915->ggtt.base, NULL);
+	if (IS_ERR(vma))
+		goto err_obj;
+
+	if (i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_MAPPABLE))
+		goto err_obj;
+
+	map = i915_vma_pin_iomap(vma);
+	if (!IS_ERR(map)) {
+		memset_io(map, 0, sz);
+		i915_vma_unpin_iomap(vma);
+	}
+
+	i915->gt_pm.pctx = vma;
+	return;
+
+err_obj:
+	i915_gem_object_put(obj);
+err:
+	DRM_DEBUG_DRIVER("not enough stolen space for PCTX, disabling\n");
+	mkwrite_device_info(i915)->has_rc6 = 0;
+	intel_runtime_pm_get(i915);
 }
 
 static void valleyview_init_gt_powersave(struct drm_i915_private *dev_priv)
@@ -2316,6 +2411,8 @@ static void __enable_rc6(struct drm_i915_private *dev_priv)
 		gen8_enable_rc6(dev_priv);
 	else if (INTEL_GEN(dev_priv) >= 6)
 		gen6_enable_rc6(dev_priv);
+	else if (INTEL_GEN(dev_priv) >= 5)
+		gen5_enable_rc6(dev_priv);
 }
 
 static void __enable_rps(struct drm_i915_private *dev_priv)
@@ -2384,6 +2481,8 @@ static void __disable_rc6(struct drm_i915_private *dev_priv)
 		valleyview_disable_rc6(dev_priv);
 	else if (INTEL_GEN(dev_priv) >= 6)
 		gen6_disable_rc6(dev_priv);
+	else if (INTEL_GEN(dev_priv) >= 5)
+		gen5_disable_rc6(dev_priv);
 }
 
 void intel_gt_disable_rc6(struct drm_i915_private *dev_priv)
@@ -2423,6 +2522,8 @@ void intel_gt_pm_fini(struct drm_i915_private *dev_priv)
 	if (IS_VALLEYVIEW(dev_priv))
 		valleyview_cleanup_gt_powersave(dev_priv);
 
+	i915_vma_unpin_and_release(&dev_priv->gt_pm.pctx);
+
 	if (!HAS_RC6(dev_priv))
 		intel_runtime_pm_put(dev_priv);
 }
-- 
2.15.1



More information about the Intel-gfx-trybot mailing list