[Intel-gfx] [PATCH 1/3] drm/i915: Extract PCU communication

Jesse Barnes jbarnes at virtuousgeek.org
Thu Sep 27 20:05:24 CEST 2012


On Wed, 26 Sep 2012 10:34:00 -0700
Ben Widawsky <ben at bwidawsk.net> wrote:

> There is a special mechanism for communicating with the PCU already
> being used for the ring frequency stuff. As we'll be needing this for
> other commands, extract it now to make future code less error prone and
> the current code more reusable.
> 
> I'm not entirely sure if this code matches 1:1 with the previous code
> behaviorally. Functionally however, it should be the same.
> 
> CC: Jesse Barnes <jbarnes at virtuousgeek.org>
> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 13 ++---
>  drivers/gpu/drm/i915/i915_drv.h     |  3 ++
>  drivers/gpu/drm/i915/intel_pm.c     | 94 +++++++++++++++++++++++--------------
>  3 files changed, 67 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 7a4b3f3..6647585 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1283,15 +1283,10 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>  	for (gpu_freq = dev_priv->rps.min_delay;
>  	     gpu_freq <= dev_priv->rps.max_delay;
>  	     gpu_freq++) {
> -		I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
> -		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
> -			   GEN6_PCODE_READ_MIN_FREQ_TABLE);
> -		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
> -			      GEN6_PCODE_READY) == 0, 10)) {
> -			DRM_ERROR("pcode read of freq table timed out\n");
> -			continue;
> -		}
> -		ia_freq = I915_READ(GEN6_PCODE_DATA);
> +		ia_freq = gpu_freq;
> +		sandybridge_pcode_read(dev_priv,
> +				       GEN6_PCODE_READ_MIN_FREQ_TABLE,
> +				       &ia_freq);
>  		seq_printf(m, "%d\t\t%d\n", gpu_freq * GT_FREQUENCY_MULTIPLIER, ia_freq * 100);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index af5ceb4..b75a7b5 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1622,6 +1622,9 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
>  void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
>  int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
>  
> +int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
> +int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
> +
>  #define __i915_read(x, y) \
>  	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index a3e4f8b..6488cd0 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2503,30 +2503,16 @@ static void gen6_enable_rps(struct drm_device *dev)
>  		   GEN6_RP_UP_BUSY_AVG |
>  		   (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT));
>  
> -	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> -		     500))
> -		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
> -
> -	I915_WRITE(GEN6_PCODE_DATA, 0);
> -	I915_WRITE(GEN6_PCODE_MAILBOX,
> -		   GEN6_PCODE_READY |
> -		   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
> -	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> -		     500))
> -		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
> -
> -	/* Check for overclock support */
> -	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> -		     500))
> -		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
> -	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
> -	pcu_mbox = I915_READ(GEN6_PCODE_DATA);
> -	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> -		     500))
> -		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
> -	if (pcu_mbox & (1<<31)) { /* OC supported */
> -		dev_priv->rps.max_delay = pcu_mbox & 0xff;
> -		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
> +	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
> +	if (!ret) {
> +		pcu_mbox = 0;
> +		ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
> +		if (ret && pcu_mbox & (1<<31)) { /* OC supported */
> +			dev_priv->rps.max_delay = pcu_mbox & 0xff;
> +			DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
> +		}
> +	} else {
> +		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
>  	}
>  
>  	gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8);
> @@ -2581,17 +2567,11 @@ static void gen6_update_ring_freq(struct drm_device *dev)
>  		else
>  			ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
>  		ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
> +		ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT;
>  
> -		I915_WRITE(GEN6_PCODE_DATA,
> -			   (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
> -			   gpu_freq);
> -		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
> -			   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
> -		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
> -			      GEN6_PCODE_READY) == 0, 10)) {
> -			DRM_ERROR("pcode write of freq table timed out\n");
> -			continue;
> -		}
> +		sandybridge_pcode_write(dev_priv,
> +					GEN6_PCODE_WRITE_MIN_FREQ_TABLE,
> +					ia_freq | gpu_freq);
>  	}
>  }
>  
> @@ -4143,3 +4123,49 @@ void intel_gt_init(struct drm_device *dev)
>  	}
>  }
>  
> +int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)
> +{
> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +
> +	if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) {
> +		DRM_DEBUG_DRIVER("warning: pcode (read) mailbox access failed\n");
> +		return -EAGAIN;
> +	}
> +
> +	I915_WRITE(GEN6_PCODE_DATA, *val);
> +	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
> +
> +	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> +		     500)) {
> +		DRM_ERROR("timeout waiting for pcode read (%d) to finish\n", mbox);
> +		return -ETIMEDOUT;
> +	}
> +
> +	*val = I915_READ(GEN6_PCODE_DATA);
> +	I915_WRITE(GEN6_PCODE_DATA, 0);
> +
> +	return 0;
> +}
> +
> +int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
> +{
> +	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +
> +	if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) {
> +		DRM_DEBUG_DRIVER("warning: pcode (write) mailbox access failed\n");
> +		return -EAGAIN;
> +	}
> +
> +	I915_WRITE(GEN6_PCODE_DATA, val);
> +	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
> +
> +	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
> +		     500)) {
> +		DRM_ERROR("timeout waiting for pcode write (%d) to finish\n", mbox);
> +		return -ETIMEDOUT;
> +	}
> +
> +	I915_WRITE(GEN6_PCODE_DATA, 0);
> +
> +	return 0;
> +}

I'd call it punit rather than pcode, but that's just a nitpick.  I like
pulling it out into a separate function.

Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center



More information about the Intel-gfx mailing list