Commit aed242ff authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm/i915: Relax RPS contraints to allows setting minfreq on idle

When we idle, we set the GPU frequency to the hardware minimum (not user
minimum). We introduce a new variable to distinguish between the
different roles, and to allow easy tuning of the idle frequency without
impacting over aspects of RPS. Setting the minimum frequency should be a
safety blanket as the pcu on the GPU should be power gating itself
anyway. However, in order for us to do set the absolute minimum
frequency, we need to relax a few of our assertions that we do not
exceed the user limits.

v2: Add idle_freq
v3: Init idle_freq for vlv and add a bunch of WARNs
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Deepak S <deepak.s@linux.intel.com>
Reviewed-by: Deepak S<deepak.s@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent edf4427b
...@@ -1200,6 +1200,9 @@ static int i915_frequency_info(struct seq_file *m, void *unused) ...@@ -1200,6 +1200,9 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
seq_printf(m, "Max overclocked frequency: %dMHz\n", seq_printf(m, "Max overclocked frequency: %dMHz\n",
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
seq_printf(m, "Idle freq: %d MHz\n",
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
} else if (IS_VALLEYVIEW(dev)) { } else if (IS_VALLEYVIEW(dev)) {
u32 freq_sts; u32 freq_sts;
...@@ -1214,6 +1217,9 @@ static int i915_frequency_info(struct seq_file *m, void *unused) ...@@ -1214,6 +1217,9 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
seq_printf(m, "min GPU freq: %d MHz\n", seq_printf(m, "min GPU freq: %d MHz\n",
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
seq_printf(m, "idle GPU freq: %d MHz\n",
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
seq_printf(m, seq_printf(m,
"efficient (RPe) frequency: %d MHz\n", "efficient (RPe) frequency: %d MHz\n",
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
......
...@@ -1025,6 +1025,7 @@ struct intel_gen6_power_mgmt { ...@@ -1025,6 +1025,7 @@ struct intel_gen6_power_mgmt {
u8 max_freq_softlimit; /* Max frequency permitted by the driver */ u8 max_freq_softlimit; /* Max frequency permitted by the driver */
u8 max_freq; /* Maximum frequency, RP0 if not overclocking */ u8 max_freq; /* Maximum frequency, RP0 if not overclocking */
u8 min_freq; /* AKA RPn. Minimum frequency */ u8 min_freq; /* AKA RPn. Minimum frequency */
u8 idle_freq; /* Frequency to request when we are idle */
u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */ u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */
u8 rp1_freq; /* "less than" RP0 power/freqency */ u8 rp1_freq; /* "less than" RP0 power/freqency */
u8 rp0_freq; /* Non-overclocked max frequency. */ u8 rp0_freq; /* Non-overclocked max frequency. */
......
...@@ -3855,9 +3855,9 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) ...@@ -3855,9 +3855,9 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
break; break;
} }
/* Max/min bins are special */ /* Max/min bins are special */
if (val == dev_priv->rps.min_freq_softlimit) if (val <= dev_priv->rps.min_freq_softlimit)
new_power = LOW_POWER; new_power = LOW_POWER;
if (val == dev_priv->rps.max_freq_softlimit) if (val >= dev_priv->rps.max_freq_softlimit)
new_power = HIGH_POWER; new_power = HIGH_POWER;
if (new_power == dev_priv->rps.power) if (new_power == dev_priv->rps.power)
return; return;
...@@ -3940,8 +3940,8 @@ static void gen6_set_rps(struct drm_device *dev, u8 val) ...@@ -3940,8 +3940,8 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
WARN_ON(val > dev_priv->rps.max_freq_softlimit); WARN_ON(val > dev_priv->rps.max_freq);
WARN_ON(val < dev_priv->rps.min_freq_softlimit); WARN_ON(val < dev_priv->rps.min_freq);
/* min/max delay may still have been modified so be sure to /* min/max delay may still have been modified so be sure to
* write the limits value. * write the limits value.
...@@ -3979,8 +3979,8 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val) ...@@ -3979,8 +3979,8 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
WARN_ON(val > dev_priv->rps.max_freq_softlimit); WARN_ON(val > dev_priv->rps.max_freq);
WARN_ON(val < dev_priv->rps.min_freq_softlimit); WARN_ON(val < dev_priv->rps.min_freq);
if (WARN_ONCE(IS_CHERRYVIEW(dev) && (val & 1), if (WARN_ONCE(IS_CHERRYVIEW(dev) && (val & 1),
"Odd GPU freq value\n")) "Odd GPU freq value\n"))
...@@ -4007,10 +4007,11 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val) ...@@ -4007,10 +4007,11 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val)
static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
u32 val = dev_priv->rps.idle_freq;
/* CHV and latest VLV don't need to force the gfx clock */ /* CHV and latest VLV don't need to force the gfx clock */
if (IS_CHERRYVIEW(dev) || dev->pdev->revision >= 0xd) { if (IS_CHERRYVIEW(dev) || dev->pdev->revision >= 0xd) {
valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); valleyview_set_rps(dev_priv->dev, val);
return; return;
} }
...@@ -4018,7 +4019,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) ...@@ -4018,7 +4019,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
* When we are idle. Drop to min voltage state. * When we are idle. Drop to min voltage state.
*/ */
if (dev_priv->rps.cur_freq <= dev_priv->rps.min_freq_softlimit) if (dev_priv->rps.cur_freq <= val)
return; return;
/* Mask turbo interrupt so that they will not come in between */ /* Mask turbo interrupt so that they will not come in between */
...@@ -4027,10 +4028,9 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) ...@@ -4027,10 +4028,9 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
vlv_force_gfx_clock(dev_priv, true); vlv_force_gfx_clock(dev_priv, true);
dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit; dev_priv->rps.cur_freq = val;
vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
dev_priv->rps.min_freq_softlimit);
if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) if (wait_for(((vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS))
& GENFREQSTATUS) == 0, 100)) & GENFREQSTATUS) == 0, 100))
...@@ -4038,8 +4038,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) ...@@ -4038,8 +4038,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
vlv_force_gfx_clock(dev_priv, false); vlv_force_gfx_clock(dev_priv, false);
I915_WRITE(GEN6_PMINTRMSK, I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val));
gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
} }
void gen6_rps_idle(struct drm_i915_private *dev_priv) void gen6_rps_idle(struct drm_i915_private *dev_priv)
...@@ -4051,7 +4050,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) ...@@ -4051,7 +4050,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
if (IS_VALLEYVIEW(dev)) if (IS_VALLEYVIEW(dev))
vlv_set_rps_idle(dev_priv); vlv_set_rps_idle(dev_priv);
else else
gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
dev_priv->rps.last_adj = 0; dev_priv->rps.last_adj = 0;
} }
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
...@@ -4209,6 +4208,8 @@ static void gen6_init_rps_frequencies(struct drm_device *dev) ...@@ -4209,6 +4208,8 @@ static void gen6_init_rps_frequencies(struct drm_device *dev)
dev_priv->rps.max_freq); dev_priv->rps.max_freq);
} }
dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
/* Preserve min/max settings in case of re-init */ /* Preserve min/max settings in case of re-init */
if (dev_priv->rps.max_freq_softlimit == 0) if (dev_priv->rps.max_freq_softlimit == 0)
dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
...@@ -4375,7 +4376,7 @@ static void gen8_enable_rps(struct drm_device *dev) ...@@ -4375,7 +4376,7 @@ static void gen8_enable_rps(struct drm_device *dev)
/* 6: Ring frequency + overclocking (our driver does this later */ /* 6: Ring frequency + overclocking (our driver does this later */
dev_priv->rps.power = HIGH_POWER; /* force a reset */ dev_priv->rps.power = HIGH_POWER; /* force a reset */
gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
} }
...@@ -4469,7 +4470,7 @@ static void gen6_enable_rps(struct drm_device *dev) ...@@ -4469,7 +4470,7 @@ static void gen6_enable_rps(struct drm_device *dev)
} }
dev_priv->rps.power = HIGH_POWER; /* force a reset */ dev_priv->rps.power = HIGH_POWER; /* force a reset */
gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
rc6vids = 0; rc6vids = 0;
ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
...@@ -4834,6 +4835,8 @@ static void valleyview_init_gt_powersave(struct drm_device *dev) ...@@ -4834,6 +4835,8 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq), intel_gpu_freq(dev_priv, dev_priv->rps.min_freq),
dev_priv->rps.min_freq); dev_priv->rps.min_freq);
dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
/* Preserve min/max settings in case of re-init */ /* Preserve min/max settings in case of re-init */
if (dev_priv->rps.max_freq_softlimit == 0) if (dev_priv->rps.max_freq_softlimit == 0)
dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
...@@ -4909,6 +4912,8 @@ static void cherryview_init_gt_powersave(struct drm_device *dev) ...@@ -4909,6 +4912,8 @@ static void cherryview_init_gt_powersave(struct drm_device *dev)
dev_priv->rps.min_freq) & 1, dev_priv->rps.min_freq) & 1,
"Odd GPU freq values\n"); "Odd GPU freq values\n");
dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
/* Preserve min/max settings in case of re-init */ /* Preserve min/max settings in case of re-init */
if (dev_priv->rps.max_freq_softlimit == 0) if (dev_priv->rps.max_freq_softlimit == 0)
dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
...@@ -5686,6 +5691,13 @@ static void intel_gen6_powersave_work(struct work_struct *work) ...@@ -5686,6 +5691,13 @@ static void intel_gen6_powersave_work(struct work_struct *work)
gen6_enable_rps(dev); gen6_enable_rps(dev);
__gen6_update_ring_freq(dev); __gen6_update_ring_freq(dev);
} }
WARN_ON(dev_priv->rps.max_freq < dev_priv->rps.min_freq);
WARN_ON(dev_priv->rps.idle_freq > dev_priv->rps.max_freq);
WARN_ON(dev_priv->rps.efficient_freq < dev_priv->rps.min_freq);
WARN_ON(dev_priv->rps.efficient_freq > dev_priv->rps.max_freq);
dev_priv->rps.enabled = true; dev_priv->rps.enabled = true;
gen6_enable_rps_interrupts(dev); gen6_enable_rps_interrupts(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment