On Tue, Jun 28, 2011 at 10:59:13AM -0700, Jesse Barnes wrote:
> The ring frequency scaling table tells the PCU to treat certain GPU
> frequencies as if they were a given CPU frequency for purposes of
> scaling the ring frequency.  Normally the PCU will scale the ring
> frequency based on the CPU P-state, but with the table present, it will
> also take the GPU frequency into account.
> 
> The main downside of keeping the ring frequency high while the CPU is
> at a low frequency (or asleep altogether) is increased power
> consumption.  But then if you're keeping your GPU busy, you probably
> want the extra performance.
> 
> v2:
>   - add units to debug table header (from Eric)
>   - use tsc_khz as a fallback if the cpufreq driver doesn't give us a freq
>     (from Chris)
> 
> Tested-by: Eric Anholt <[email protected]>
> Reviewed-by: Eric Anholt <[email protected]>
> Signed-off-by: Jesse Barnes <[email protected]>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c  |   43 +++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h      |    4 ++-
>  drivers/gpu/drm/i915/i915_suspend.c  |    4 ++-
>  drivers/gpu/drm/i915/intel_display.c |   57 
> +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |    1 +
>  5 files changed, 106 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 4d46441..4d3ddff 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1123,6 +1123,48 @@ static int i915_emon_status(struct seq_file *m, void 
> *unused)
>       return 0;
>  }
>  
> +static int i915_ring_freq_table(struct seq_file *m, void *unused)
> +{
> +     struct drm_info_node *node = (struct drm_info_node *) m->private;
> +     struct drm_device *dev = node->minor->dev;
> +     drm_i915_private_t *dev_priv = dev->dev_private;
> +     int ret;
> +     int gpu_freq, ia_freq;
> +
> +     if (!IS_GEN6(dev)) {
> +             seq_printf(m, "unsupported on this chipset\n");
> +             return 0;
> +     }
> +
> +     ret = mutex_lock_interruptible(&dev->struct_mutex);
> +     if (ret)
> +             return ret;
> +
> +     gen6_gt_force_wake_get(dev_priv);
> +
> +     seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
> +
> +     for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->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 write of freq table timed out\n");
> +                     continue;
> +             }
> +             ia_freq = I915_READ(GEN6_PCODE_DATA);
> +             seq_printf(m, "%d\t\t%d\n", gpu_freq * 50, ia_freq * 100);
> +     }
> +
> +     gen6_gt_force_wake_put(dev_priv);
> +
> +     mutex_unlock(&dev->struct_mutex);
> +
> +     return 0;
> +}
> +
>  static int i915_gfxec(struct seq_file *m, void *unused)
>  {
>       struct drm_info_node *node = (struct drm_info_node *) m->private;

You shouldn't need any of the forcewake stuff here, unless I'm missing
something.

> @@ -7159,6 +7160,58 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
>       mutex_unlock(&dev_priv->dev->struct_mutex);
>  }
>  
> +void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
> +{
> +     int min_freq = 15;
> +     int gpu_freq, ia_freq, max_ia_freq;
> +     int scaling_factor = 180;
> +
> +     max_ia_freq = cpufreq_quick_get_max(0);
> +     /* default to 3GHz if none found, PCU will ensure we don't go over */
> +     if (!max_ia_freq)
> +             max_ia_freq = tsc_khz;
> +
> +     /* Convert from kHz to MHz */
> +     max_ia_freq /= 1000;
> +
> +     mutex_lock(&dev_priv->dev->struct_mutex);
> +     gen6_gt_force_wake_get(dev_priv);
> +
> +     /*
> +      * For each potential GPU frequency, load a ring frequency we'd like
> +      * to use for memory access.  We do this by specifying the IA frequency
> +      * the PCU should use as a reference to determine the ring frequency.
> +      */
> +     for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
> +          gpu_freq--) {
> +             int diff = dev_priv->max_delay - gpu_freq;
> +
> +             /*
> +              * For GPU frequencies less than 750MHz, just use the lowest
> +              * ring freq.
> +              */
> +             if (gpu_freq < min_freq)
> +                     ia_freq = 800;
> +             else
> +                     ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
> +             ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
> +
> +             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;
> +             }
> +     }
> +
> +     gen6_gt_force_wake_put(dev_priv);
> +     mutex_unlock(&dev_priv->dev->struct_mutex);
> +}
> +
>  static void ironlake_init_clock_gating(struct drm_device *dev)
>  {
>       struct drm_i915_private *dev_priv = dev->dev_private;


Same: you shouldn't need any of the forcewake stuff here, unless I'm
missing something.

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to