[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