[Intel-gfx] [PATCH] drm/i915: Adjustable Render Power State policies

Chris Wilson chris at chris-wilson.co.uk
Sat Jul 27 00:24:11 CEST 2013


As a complement to the suggestions put forward by Jesse in

drm/i915: "Scotty, I need more power!"
(1372436290-3297-1-git-send-email-jbarnes at virtuousgeek.org)

and

drm/i915: boost GPU and CPU freq when leaving idle
(1372438472-3233-1-git-send-email-jbarnes at virtuousgeek.org)

we also have the ability to fine tune how we respond to the GPU's
requests for more power.

This patch introduces the i915.rps_policy module parameter that adjusts
how we respond to the upclock request:

  1 - Powersaving (current implementation)
      Increase the frequency by one bin on every upclock request.

  2 - Conservative (new default)
      When waking from idle, boost the render frequency to the
      default render frequency (RP1)

  3 - Ondemand
      At every upclock request, increase to halfway between the current
      frequency and maximum. This should give rapid upclocking similar
      to tcp window scaling.

  4 - Performance
      Every time the GPU wants more power, give it everything we have.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.c |  8 +++++++
 drivers/gpu/drm/i915/i915_drv.h |  2 ++
 drivers/gpu/drm/i915/i915_irq.c | 46 +++++++++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_pm.c |  1 +
 4 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 1d8cedc..7ad80f4 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -72,6 +72,14 @@ MODULE_PARM_DESC(i915_enable_rc6,
 		"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
 		"default: -1 (use per-chip default)");
 
+int i915_rps_policy __read_mostly = 1;
+module_param_named(rps_policy, i915_rps_policy, int, 0600);
+MODULE_PARM_DESC(rps_policy,
+		"Specify a policy to use to respond to requests to change the render clock. "
+		"Different levels of uplocking agressiveness can be selected"
+		"(0 = Powersaving, slowly uplock; 1 = Conservative, when the gpu wakes from idle go straight to RP1/RPe (recommended minimum active GPU frequency); 2 = Ondemand, rapidly increase frequency whilst upclocking; 4 = Performance, always upclock to maximum frequency). "
+		"default: 1 (Conservative)");
+
 int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
 MODULE_PARM_DESC(i915_enable_fbc,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ec14124..71232bc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -811,6 +811,7 @@ struct intel_gen6_power_mgmt {
 	u8 min_delay;
 	u8 max_delay;
 	u8 rpe_delay;
+	u8 rp1_delay;
 	u8 hw_max;
 
 	struct delayed_work delayed_resume_work;
@@ -1635,6 +1636,7 @@ extern int i915_lvds_channel_mode __read_mostly;
 extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
 extern int i915_enable_rc6 __read_mostly;
+extern int i915_rps_policy __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ee3e49c..edd73c0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -728,14 +728,32 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
-		new_delay = dev_priv->rps.cur_delay + 1;
+		switch (i915_rps_policy) {
+		case 0: /* Powersave, slow increase in frequency */
+			new_delay = dev_priv->rps.cur_delay + 1;
+			break;
+
+		case 1: /* Conservative, jump directly to RPe */
+			new_delay = dev_priv->rps.rp1_delay;
+			if (dev_priv->rps.cur_delay >= new_delay)
+				new_delay = dev_priv->rps.cur_delay + 1;
+			break;
+
+		case 2: /* Ondemand, halfway to maximum */
+			new_delay = dev_priv->rps.cur_delay + 1;
+			if (new_delay < dev_priv->rps.rp1_delay)
+				new_delay = dev_priv->rps.rp1_delay;
+			else
+				new_delay = (dev_priv->rps.max_delay + new_delay) >> 1;
+			break;
+
+		default: /* Performance, straight to maximum */
+			new_delay = dev_priv->rps.max_delay;
+			break;
+		}
 
-		/*
-		 * For better performance, jump directly
-		 * to RPe if we're below it.
-		 */
 		if (IS_VALLEYVIEW(dev_priv->dev) &&
-		    dev_priv->rps.cur_delay < dev_priv->rps.rpe_delay)
+		    new_delay < dev_priv->rps.rpe_delay)
 			new_delay = dev_priv->rps.rpe_delay;
 	} else
 		new_delay = dev_priv->rps.cur_delay - 1;
@@ -743,13 +761,15 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	/* sysfs frequency interfaces may have snuck in while servicing the
 	 * interrupt
 	 */
-	if (new_delay >= dev_priv->rps.min_delay &&
-	    new_delay <= dev_priv->rps.max_delay) {
-		if (IS_VALLEYVIEW(dev_priv->dev))
-			valleyview_set_rps(dev_priv->dev, new_delay);
-		else
-			gen6_set_rps(dev_priv->dev, new_delay);
-	}
+	if (new_delay < dev_priv->rps.min_delay)
+		new_delay = dev_priv->rps.min_delay;
+	if (new_delay > dev_priv->rps.max_delay)
+		new_delay = dev_priv->rps.max_delay;
+
+	if (IS_VALLEYVIEW(dev_priv->dev))
+		valleyview_set_rps(dev_priv->dev, new_delay);
+	else
+		gen6_set_rps(dev_priv->dev, new_delay);
 
 	if (IS_VALLEYVIEW(dev_priv->dev)) {
 		/*
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 4e6d618..e9e467c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3242,6 +3242,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	/* In units of 50MHz */
 	dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
 	dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16;
+	dev_priv->rps.rp1_delay = (rp_state_cap & 0xff00) >> 8;
 	dev_priv->rps.cur_delay = 0;
 
 	/* disable the counters and set deterministic thresholds */
-- 
1.8.3.2




More information about the Intel-gfx mailing list