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