diff mbox

[v3,2/3] drm/i915/vlv: WA to fix Voltage not getting dropped to Vmin when Gfx is power gated.

Message ID 1390223426-27627-3-git-send-email-deepak.s@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

deepak.s@intel.com Jan. 20, 2014, 1:10 p.m. UTC
From: Deepak S <deepak.s@intel.com>

When we enter RC6 and GFX Clocks are off, the voltage remains higher
than Vmin. When we try to set the freq to RPe, it might fail since the
Gfx clocks are down. So to fix this in Gfx idle, Bring the GFX clock up
and set the freq to RPe then move GFx down.

v2: remove vlv_update_rps_cur_delay function. Update commit message (Daniel)

v3: Fix the timeout during wait for gfx clock (Jesse)

Signed-off-by: Deepak S <deepak.s@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h |  4 ++++
 drivers/gpu/drm/i915/intel_pm.c | 48 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

Comments

Ville Syrjälä Jan. 21, 2014, 2:43 p.m. UTC | #1
On Mon, Jan 20, 2014 at 06:40:25PM +0530, deepak.s@intel.com wrote:
> From: Deepak S <deepak.s@intel.com>
> 
> When we enter RC6 and GFX Clocks are off, the voltage remains higher
> than Vmin. When we try to set the freq to RPe, it might fail since the
> Gfx clocks are down. So to fix this in Gfx idle, Bring the GFX clock up
> and set the freq to RPe then move GFx down.
> 
> v2: remove vlv_update_rps_cur_delay function. Update commit message (Daniel)
> 
> v3: Fix the timeout during wait for gfx clock (Jesse)
> 
> Signed-off-by: Deepak S <deepak.s@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |  4 ++++
>  drivers/gpu/drm/i915/intel_pm.c | 48 ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cc2f3de..e1d5f31 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4944,6 +4944,10 @@
>  						 GEN6_PM_RP_DOWN_THRESHOLD | \
>  						 GEN6_PM_RP_DOWN_TIMEOUT)
>  
> +#define VLV_GTLC_SURVIVABILITY_REG              0x130098
> +#define VLV_GFX_CLK_STATUS_BIT			(1<<3)
> +#define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
> +
>  #define GEN6_GT_GFX_RC6_LOCKED			0x138104
>  #define VLV_COUNTER_CONTROL			0x138104
>  #define   VLV_COUNT_RANGE_HIGH			(1<<15)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index d00a2cf..86d87e5 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3035,6 +3035,51 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
>  	trace_intel_gpu_freq_change(val * 50);
>  }
>  
> +/* vlv_set_rps_idle: Set the frequency to Rpe if Gfx clocks are down
> + *
> + * * If Gfx is Idle, then
> + * 1. Mask Turbo interrupts
> + * 2. Bring up Gfx clock
> + * 3. Change the freq to Rpe and wait till P-Unit updates freq
> + * 4. Clear the Force GFX CLK ON bit so that Gfx can down
> + * 5. Unmask Turbo interrupts
> +*/
> +static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
> +{
> +	/*
> +	 * When we are idle.  Drop to min voltage state.
> +	 */
> +
> +	if (dev_priv->rps.cur_delay == dev_priv->rps.rpe_delay)
> +		return;
> +
> +	/* Mask turbo interrupt so that they will not come in between */
> +	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> +
> +	/* Bring up the Gfx clock */
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
> +				VLV_GFX_CLK_FORCE_ON_BIT);
> +
> +	if (wait_for_atomic_us(((VLV_GFX_CLK_STATUS_BIT &
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 500)) {
> +			DRM_ERROR("GFX_CLK_ON request timed out\n");
> +		return;
> +	}
> +
> +	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);

We're not actually waiting for Punit here. Should we?

Also valleyview_set_rps() won't actually do anything if cur_delay ==
rpe_delay. Are we required to actually poke the Punit here, or is it
enough that we had already previously requested <=rpe_delay? In that
case I think it might make sense to skip this if cur_delay <= rpe_delay.
But if we really need to poke Punit to make sure it changes the
frequency/voltage, then I guess we should force the issue by eg. setting
cur_delay=0 just before calling valleyview_set_rps().

> +
> +	/* Release the Gfx clock */
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
> +				~VLV_GFX_CLK_FORCE_ON_BIT);
> +
> +	/* Unmask Turbo interrupts */
> +	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
> +}
> +
> +
> +
>  void gen6_rps_idle(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> @@ -3042,7 +3087,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	if (dev_priv->rps.enabled) {
>  		if (IS_VALLEYVIEW(dev))
> -			valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
> +			vlv_set_rps_idle(dev_priv);
>  		else
>  			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
>  		dev_priv->rps.last_adj = 0;
> @@ -4273,6 +4318,7 @@ void intel_gpu_ips_teardown(void)
>  	i915_mch_dev = NULL;
>  	spin_unlock_irq(&mchdev_lock);
>  }
> +
>  static void intel_init_emon(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -- 
> 1.8.4.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
deepak.s@intel.com Jan. 21, 2014, 3:29 p.m. UTC | #2
>We're not actually waiting for Punit here. Should we?
Ideally yes, we need to wait for the Punit to grant the freq. Based on your suggestion on  " vlv_update_rps_cur_delay"  that the punit will recheck the situation periodically, and it will try to use PUNIT_REG_GPU_FREQ_REQ. I removed the wait form this patch.
I do believe we need to wait here.  To make sure the requested freq is set before bring down the Gfx clk.

>Also valleyview_set_rps() won't actually do anything if cur_delay == rpe_delay. Are we required to actually poke the Punit here, or is it enough that we had already previously requested <=rpe_delay? In that case I think it might make sense to skip this if cur_delay <= rpe_delay.
>But if we really need to poke Punit to make sure it changes the frequency/voltage, then I guess we should force the issue by eg. setting
>cur_delay=0 just before calling valleyview_set_rps().
I agree, I think instead of valleyview_set_rps we can use " vlv_punit_write" and request the freq and wait for punit to grant the freq if required. 


Btw, still using outlook, I will send the next replay from new email client :)

-----Original Message-----
From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com] 
Sent: Tuesday, January 21, 2014 8:13 PM
To: S, Deepak
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH v3 2/3] drm/i915/vlv: WA to fix Voltage not getting dropped to Vmin when Gfx is power gated.

On Mon, Jan 20, 2014 at 06:40:25PM +0530, deepak.s@intel.com wrote:
> From: Deepak S <deepak.s@intel.com>
> 
> When we enter RC6 and GFX Clocks are off, the voltage remains higher 
> than Vmin. When we try to set the freq to RPe, it might fail since the 
> Gfx clocks are down. So to fix this in Gfx idle, Bring the GFX clock 
> up and set the freq to RPe then move GFx down.
> 
> v2: remove vlv_update_rps_cur_delay function. Update commit message 
> (Daniel)
> 
> v3: Fix the timeout during wait for gfx clock (Jesse)
> 
> Signed-off-by: Deepak S <deepak.s@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |  4 ++++  
> drivers/gpu/drm/i915/intel_pm.c | 48 
> ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h 
> b/drivers/gpu/drm/i915/i915_reg.h index cc2f3de..e1d5f31 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4944,6 +4944,10 @@
>  						 GEN6_PM_RP_DOWN_THRESHOLD | \
>  						 GEN6_PM_RP_DOWN_TIMEOUT)
>  
> +#define VLV_GTLC_SURVIVABILITY_REG              0x130098
> +#define VLV_GFX_CLK_STATUS_BIT			(1<<3)
> +#define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
> +
>  #define GEN6_GT_GFX_RC6_LOCKED			0x138104
>  #define VLV_COUNTER_CONTROL			0x138104
>  #define   VLV_COUNT_RANGE_HIGH			(1<<15)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c 
> b/drivers/gpu/drm/i915/intel_pm.c index d00a2cf..86d87e5 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3035,6 +3035,51 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
>  	trace_intel_gpu_freq_change(val * 50);  }
>  
> +/* vlv_set_rps_idle: Set the frequency to Rpe if Gfx clocks are down
> + *
> + * * If Gfx is Idle, then
> + * 1. Mask Turbo interrupts
> + * 2. Bring up Gfx clock
> + * 3. Change the freq to Rpe and wait till P-Unit updates freq
> + * 4. Clear the Force GFX CLK ON bit so that Gfx can down
> + * 5. Unmask Turbo interrupts
> +*/
> +static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) {
> +	/*
> +	 * When we are idle.  Drop to min voltage state.
> +	 */
> +
> +	if (dev_priv->rps.cur_delay == dev_priv->rps.rpe_delay)
> +		return;
> +
> +	/* Mask turbo interrupt so that they will not come in between */
> +	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> +
> +	/* Bring up the Gfx clock */
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
> +				VLV_GFX_CLK_FORCE_ON_BIT);
> +
> +	if (wait_for_atomic_us(((VLV_GFX_CLK_STATUS_BIT &
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 500)) {
> +			DRM_ERROR("GFX_CLK_ON request timed out\n");
> +		return;
> +	}
> +
> +	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);

We're not actually waiting for Punit here. Should we?

Also valleyview_set_rps() won't actually do anything if cur_delay == rpe_delay. Are we required to actually poke the Punit here, or is it enough that we had already previously requested <=rpe_delay? In that case I think it might make sense to skip this if cur_delay <= rpe_delay.
But if we really need to poke Punit to make sure it changes the frequency/voltage, then I guess we should force the issue by eg. setting
cur_delay=0 just before calling valleyview_set_rps().

> +
> +	/* Release the Gfx clock */
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> +		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
> +				~VLV_GFX_CLK_FORCE_ON_BIT);
> +
> +	/* Unmask Turbo interrupts */
> +	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS); }
> +
> +
> +
>  void gen6_rps_idle(struct drm_i915_private *dev_priv)  {
>  	struct drm_device *dev = dev_priv->dev; @@ -3042,7 +3087,7 @@ void 
> gen6_rps_idle(struct drm_i915_private *dev_priv)
>  	mutex_lock(&dev_priv->rps.hw_lock);
>  	if (dev_priv->rps.enabled) {
>  		if (IS_VALLEYVIEW(dev))
> -			valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
> +			vlv_set_rps_idle(dev_priv);
>  		else
>  			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
>  		dev_priv->rps.last_adj = 0;
> @@ -4273,6 +4318,7 @@ void intel_gpu_ips_teardown(void)
>  	i915_mch_dev = NULL;
>  	spin_unlock_irq(&mchdev_lock);
>  }
> +
>  static void intel_init_emon(struct drm_device *dev)  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> --
> 1.8.4.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

--
Ville Syrjälä
Intel OTC
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cc2f3de..e1d5f31 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4944,6 +4944,10 @@ 
 						 GEN6_PM_RP_DOWN_THRESHOLD | \
 						 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define VLV_GTLC_SURVIVABILITY_REG              0x130098
+#define VLV_GFX_CLK_STATUS_BIT			(1<<3)
+#define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
+
 #define GEN6_GT_GFX_RC6_LOCKED			0x138104
 #define VLV_COUNTER_CONTROL			0x138104
 #define   VLV_COUNT_RANGE_HIGH			(1<<15)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d00a2cf..86d87e5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3035,6 +3035,51 @@  void gen6_set_rps(struct drm_device *dev, u8 val)
 	trace_intel_gpu_freq_change(val * 50);
 }
 
+/* vlv_set_rps_idle: Set the frequency to Rpe if Gfx clocks are down
+ *
+ * * If Gfx is Idle, then
+ * 1. Mask Turbo interrupts
+ * 2. Bring up Gfx clock
+ * 3. Change the freq to Rpe and wait till P-Unit updates freq
+ * 4. Clear the Force GFX CLK ON bit so that Gfx can down
+ * 5. Unmask Turbo interrupts
+*/
+static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
+{
+	/*
+	 * When we are idle.  Drop to min voltage state.
+	 */
+
+	if (dev_priv->rps.cur_delay == dev_priv->rps.rpe_delay)
+		return;
+
+	/* Mask turbo interrupt so that they will not come in between */
+	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+
+	/* Bring up the Gfx clock */
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
+				VLV_GFX_CLK_FORCE_ON_BIT);
+
+	if (wait_for_atomic_us(((VLV_GFX_CLK_STATUS_BIT &
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 500)) {
+			DRM_ERROR("GFX_CLK_ON request timed out\n");
+		return;
+	}
+
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
+
+	/* Release the Gfx clock */
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
+		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
+				~VLV_GFX_CLK_FORCE_ON_BIT);
+
+	/* Unmask Turbo interrupts */
+	I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS);
+}
+
+
+
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -3042,7 +3087,7 @@  void gen6_rps_idle(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
 		if (IS_VALLEYVIEW(dev))
-			valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
+			vlv_set_rps_idle(dev_priv);
 		else
 			gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
 		dev_priv->rps.last_adj = 0;
@@ -4273,6 +4318,7 @@  void intel_gpu_ips_teardown(void)
 	i915_mch_dev = NULL;
 	spin_unlock_irq(&mchdev_lock);
 }
+
 static void intel_init_emon(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;