Since commit aed242ff7ebb697e4dff912bd4dc7ec7192f7581
Author: Chris Wilson <ch...@chris-wilson.co.uk>
Date:   Wed Mar 18 09:48:21 2015 +0000

    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).

Let's add sysfs/debugfs knobs allowing userspace to control idle
frequency, similar to softmin/softmax frequency.

Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Signed-off-by: Michał Winiarski <michal.winiar...@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 69 ++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_sysfs.c   | 69 ++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_pm.c     | 20 ++++++-----
 3 files changed, 148 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 24f4105..6988213 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5050,7 +5050,9 @@ i915_min_freq_set(void *data, u64 val)
        hw_max = dev_priv->rps.max_freq;
        hw_min = dev_priv->rps.min_freq;
 
-       if (val < hw_min || val > hw_max || val > 
dev_priv->rps.max_freq_softlimit) {
+       if (val < hw_min || val > hw_max ||
+           val > dev_priv->rps.max_freq_softlimit ||
+           val < dev_priv->rps.idle_freq) {
                mutex_unlock(&dev_priv->rps.hw_lock);
                return -EINVAL;
        }
@@ -5069,6 +5071,70 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops,
                        "%llu\n");
 
 static int
+i915_idle_freq_get(void *data, u64 *val)
+{
+       struct drm_device *dev = data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if (INTEL_INFO(dev)->gen < 6)
+               return -ENODEV;
+
+       flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+       ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
+       if (ret)
+               return ret;
+
+       *val = intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       return 0;
+}
+
+static int
+i915_idle_freq_set(void *data, u64 val)
+{
+       struct drm_device *dev = data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 hw_max, hw_min;
+       int ret;
+
+       if (INTEL_INFO(dev)->gen < 6)
+               return -ENODEV;
+
+       flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+       DRM_DEBUG_DRIVER("Manually setting idle freq to %llu\n", val);
+
+       ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
+       if (ret)
+               return ret;
+
+       val = intel_freq_opcode(dev_priv, val);
+
+       hw_max = dev_priv->rps.max_freq;
+       hw_min = dev_priv->rps.min_freq;
+
+       if (val < hw_min || val > hw_max || val > 
dev_priv->rps.min_freq_softlimit) {
+               mutex_unlock(&dev_priv->rps.hw_lock);
+               return -EINVAL;
+       }
+
+       dev_priv->rps.idle_freq = val;
+
+       intel_set_rps(dev_priv, val);
+
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_idle_freq_fops,
+                       i915_idle_freq_get, i915_idle_freq_set,
+                       "%llu\n");
+
+static int
 i915_cache_sharing_get(void *data, u64 *val)
 {
        struct drm_device *dev = data;
@@ -5436,6 +5502,7 @@ static const struct i915_debugfs_files {
        {"i915_wedged", &i915_wedged_fops},
        {"i915_max_freq", &i915_max_freq_fops},
        {"i915_min_freq", &i915_min_freq_fops},
+       {"i915_idle_freq", &i915_idle_freq_fops},
        {"i915_cache_sharing", &i915_cache_sharing_fops},
        {"i915_ring_stop", &i915_ring_stop_fops},
        {"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c 
b/drivers/gpu/drm/i915/i915_sysfs.c
index 37b6444..1c6930a 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -445,7 +445,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
        if (val < dev_priv->rps.min_freq ||
            val > dev_priv->rps.max_freq ||
-           val > dev_priv->rps.max_freq_softlimit) {
+           val > dev_priv->rps.max_freq_softlimit ||
+           val < dev_priv->rps.idle_freq) {
                mutex_unlock(&dev_priv->rps.hw_lock);
                intel_runtime_pm_put(dev_priv);
                return -EINVAL;
@@ -470,10 +471,74 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 }
 
+static ssize_t gt_idle_freq_mhz_show(struct device *kdev, struct 
device_attribute *attr, char *buf)
+{
+       struct drm_minor *minor = dev_to_drm_minor(kdev);
+       struct drm_device *dev = minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+
+       flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       ret = intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+static ssize_t gt_idle_freq_mhz_store(struct device *kdev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct drm_minor *minor = dev_to_drm_minor(kdev);
+       struct drm_device *dev = minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val;
+       ssize_t ret;
+
+       ret = kstrtou32(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+       intel_runtime_pm_get(dev_priv);
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+
+       val = intel_freq_opcode(dev_priv, val);
+
+       if (val < dev_priv->rps.min_freq ||
+           val > dev_priv->rps.max_freq ||
+           val > dev_priv->rps.min_freq_softlimit) {
+               mutex_unlock(&dev_priv->rps.hw_lock);
+               intel_runtime_pm_put(dev_priv);
+               return -EINVAL;
+       }
+
+       dev_priv->rps.idle_freq = val;
+
+       val = clamp_t(int, dev_priv->rps.cur_freq,
+                     dev_priv->rps.min_freq_softlimit,
+                     dev_priv->rps.max_freq_softlimit);
+
+       /* We still need *_set_rps to process the new min_delay and
+        * update the interrupt limits and PMINTRMSK even though
+        * frequency request may be unchanged. */
+       intel_set_rps(dev_priv, val);
+
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       intel_runtime_pm_put(dev_priv);
+
+       return count;
+}
+
 static DEVICE_ATTR(gt_act_freq_mhz, S_IRUGO, gt_act_freq_mhz_show, NULL);
 static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL);
 static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, 
gt_max_freq_mhz_store);
 static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, 
gt_min_freq_mhz_store);
+static DEVICE_ATTR(gt_idl_freq_mhz, S_IRUGO | S_IWUSR, gt_idle_freq_mhz_show, 
gt_idle_freq_mhz_store);
 
 static DEVICE_ATTR(vlv_rpe_freq_mhz, S_IRUGO, vlv_rpe_freq_mhz_show, NULL);
 
@@ -507,6 +572,7 @@ static const struct attribute *gen6_attrs[] = {
        &dev_attr_gt_cur_freq_mhz.attr,
        &dev_attr_gt_max_freq_mhz.attr,
        &dev_attr_gt_min_freq_mhz.attr,
+       &dev_attr_gt_idl_freq_mhz.attr,
        &dev_attr_gt_RP0_freq_mhz.attr,
        &dev_attr_gt_RP1_freq_mhz.attr,
        &dev_attr_gt_RPn_freq_mhz.attr,
@@ -518,6 +584,7 @@ static const struct attribute *vlv_attrs[] = {
        &dev_attr_gt_cur_freq_mhz.attr,
        &dev_attr_gt_max_freq_mhz.attr,
        &dev_attr_gt_min_freq_mhz.attr,
+       &dev_attr_gt_idl_freq_mhz.attr,
        &dev_attr_gt_RP0_freq_mhz.attr,
        &dev_attr_gt_RP1_freq_mhz.attr,
        &dev_attr_gt_RPn_freq_mhz.attr,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 287a885..1f84f21 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4954,12 +4954,13 @@ static void gen6_init_rps_frequencies(struct 
drm_i915_private *dev_priv)
                dev_priv->rps.efficient_freq *= GEN9_FREQ_SCALER;
        }
 
-       dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
-
-       /* Preserve min/max settings in case of re-init */
+       /* Preserve min/max/idle settings in case of re-init */
        if (dev_priv->rps.max_freq_softlimit == 0)
                dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
 
+       if (dev_priv->rps.idle_freq == 0)
+               dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
+
        if (dev_priv->rps.min_freq_softlimit == 0) {
                if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                        dev_priv->rps.min_freq_softlimit =
@@ -5612,12 +5613,14 @@ static void valleyview_init_gt_powersave(struct 
drm_i915_private *dev_priv)
                         intel_gpu_freq(dev_priv, 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/idle settings in case of re-init */
        if (dev_priv->rps.max_freq_softlimit == 0)
                dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
 
+       if (dev_priv->rps.idle_freq == 0)
+               dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
+
        if (dev_priv->rps.min_freq_softlimit == 0)
                dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
 
@@ -5676,12 +5679,13 @@ static void cherryview_init_gt_powersave(struct 
drm_i915_private *dev_priv)
                   dev_priv->rps.min_freq) & 1,
                  "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/idle settings in case of re-init */
        if (dev_priv->rps.max_freq_softlimit == 0)
                dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
 
+       if (dev_priv->rps.idle_freq == 0)
+               dev_priv->rps.idle_freq = dev_priv->rps.min_freq;
+
        if (dev_priv->rps.min_freq_softlimit == 0)
                dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
 
-- 
2.8.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to