Update sysfs functions to set SLPC parameters when setting max/min user
frequency limits.

v1: Update for SLPC 2015.2.4 (params for both slice and unslice). Replace
    HAS_SLPC with intel_slpc_active() (Paulo)

v2-v4: Rebase.

v5: Removed typecasting the frequency values to u32. (Chris). Changed
    intel_slpc_active to guc.slpc.enabled. Carved out SLPC helpers to set
    min and max frequencies.

v6: Rebase. Doing explicit SLPC reset on setting frequency to start sane
    and covered with RPM get/put. Caching SLPC limits post enabling first.

v7: Rebase due to change in the dev_priv->pm.rps structure.

v8: Updated returns from gt_min_freq_mhz_store and gt_max_freq_mhz_store
    and i915_min_freq_set and i915_max_freq_set.

v9: Rebase. Debugfs interfaces will be removed hence only updated sysfs.

Signed-off-by: Sagar Arun Kamble <sagar.a.kam...@intel.com>
Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahti...@linux.intel.com>
Cc: Radoslaw Szwichtenberg <radoslaw.szwichtenb...@intel.com>
Cc: Michal Wajdeczko <michal.wajdec...@intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundare...@intel.com>
Cc: Jeff McGee <jeff.mc...@intel.com>
---
 drivers/gpu/drm/i915/i915_sysfs.c     | 52 +++++++++++++++++----
 drivers/gpu/drm/i915/intel_guc_slpc.c | 86 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_guc_slpc.h |  6 +++
 3 files changed, 133 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c 
b/drivers/gpu/drm/i915/i915_sysfs.c
index c3083fa..d1b4793 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -343,10 +343,20 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct 
device_attribute *attr, char *buf)
 {
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
+       struct intel_guc_slpc *slpc = &dev_priv->guc.slpc;
+       u32 freq;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       intel_gpu_freq(dev_priv,
-                                      dev_priv->gt_pm.rps.max_freq_softlimit));
+       if (USES_GUC_SLPC(dev_priv)) {
+               mutex_lock(&slpc->lock);
+               freq = dev_priv->guc.slpc.max_unslice_freq;
+               mutex_unlock(&slpc->lock);
+       } else {
+               mutex_lock(&dev_priv->pcu_lock);
+               freq = dev_priv->gt_pm.rps.max_freq_softlimit;
+               mutex_lock(&dev_priv->pcu_lock);
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, freq));
 }
 
 static ssize_t gt_max_freq_mhz_store(struct device *kdev,
@@ -362,12 +372,17 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        if (ret)
                return ret;
 
+       val = intel_freq_opcode(dev_priv, val);
+
+       if (USES_GUC_SLPC(dev_priv)) {
+               ret = intel_guc_slpc_max_freq_set(&dev_priv->guc.slpc, val);
+               goto out;
+       }
+
        intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->pcu_lock);
 
-       val = intel_freq_opcode(dev_priv, val);
-
        if (val < rps->min_freq ||
            val > rps->max_freq ||
            val < rps->min_freq_softlimit) {
@@ -395,16 +410,27 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
        intel_runtime_pm_put(dev_priv);
 
+out:
        return ret ?: count;
 }
 
 static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct 
device_attribute *attr, char *buf)
 {
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
+       struct intel_guc_slpc *slpc = &dev_priv->guc.slpc;
+       u32 freq;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       intel_gpu_freq(dev_priv,
-                                      dev_priv->gt_pm.rps.min_freq_softlimit));
+       if (USES_GUC_SLPC(dev_priv)) {
+               mutex_lock(&slpc->lock);
+               freq = dev_priv->guc.slpc.min_unslice_freq;
+               mutex_unlock(&slpc->lock);
+       } else {
+               mutex_lock(&dev_priv->pcu_lock);
+               freq = dev_priv->gt_pm.rps.min_freq_softlimit;
+               mutex_lock(&dev_priv->pcu_lock);
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, freq));
 }
 
 static ssize_t gt_min_freq_mhz_store(struct device *kdev,
@@ -420,12 +446,17 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        if (ret)
                return ret;
 
+       val = intel_freq_opcode(dev_priv, val);
+
+       if (USES_GUC_SLPC(dev_priv)) {
+               ret = intel_guc_slpc_min_freq_set(&dev_priv->guc.slpc, val);
+               goto out;
+       }
+
        intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->pcu_lock);
 
-       val = intel_freq_opcode(dev_priv, val);
-
        if (val < rps->min_freq ||
            val > rps->max_freq ||
            val > rps->max_freq_softlimit) {
@@ -449,6 +480,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
        intel_runtime_pm_put(dev_priv);
 
+out:
        return ret ?: count;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_guc_slpc.c 
b/drivers/gpu/drm/i915/intel_guc_slpc.c
index 011e442..34a5963 100644
--- a/drivers/gpu/drm/i915/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/intel_guc_slpc.c
@@ -630,7 +630,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
  */
 int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 {
-       struct slpc_shared_data *data;
+       struct slpc_shared_data *data, output;
        struct page *page;
 
        mutex_lock(&slpc->lock);
@@ -652,7 +652,91 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 
        DRM_INFO("SLPC state: %s\n", slpc_get_state(slpc));
 
+       slpc_read_shared_data(slpc, &output);
+       slpc->max_unslice_freq = output.task_state_data.max_unslice_freq *
+                                GEN9_FREQ_SCALER;
+       slpc->min_unslice_freq = output.task_state_data.min_unslice_freq *
+                                GEN9_FREQ_SCALER;
+
+       mutex_unlock(&slpc->lock);
+
+       return 0;
+}
+
+/**
+ * intel_guc_slpc_max_freq_set() - Set max frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: encoded frequency
+ *
+ * This function will invoke GuC SLPC action to update the max frequency
+ * limit.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_max_freq_set(struct intel_guc_slpc *slpc, u32 val)
+{
+       struct intel_guc *guc = slpc_to_guc(slpc);
+       struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+       if (val < dev_priv->gt_pm.rps.min_freq ||
+           val > dev_priv->gt_pm.rps.max_freq ||
+           val < slpc->min_unslice_freq)
+               return -EINVAL;
+
+       intel_runtime_pm_get(dev_priv);
+       mutex_lock(&slpc->lock);
+
+       slpc_set_param(slpc,
+                      SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
+                      intel_gpu_freq(dev_priv, val));
+       slpc_set_param(slpc,
+                      SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ,
+                      intel_gpu_freq(dev_priv, val));
+
+       host2guc_slpc_reset(slpc);
+       slpc->max_unslice_freq = val;
+
+       mutex_unlock(&slpc->lock);
+       intel_runtime_pm_put(dev_priv);
+
+       return 0;
+}
+
+/**
+ * intel_guc_slpc_min_freq_set() - Set min frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: encoded frequency
+ *
+ * This function will invoke GuC SLPC action to update the min frequency
+ * limit.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_min_freq_set(struct intel_guc_slpc *slpc, u32 val)
+{
+       struct intel_guc *guc = slpc_to_guc(slpc);
+       struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+       if (val < dev_priv->gt_pm.rps.min_freq ||
+           val > dev_priv->gt_pm.rps.max_freq ||
+           val > slpc->max_unslice_freq)
+               return -EINVAL;
+
+       intel_runtime_pm_get(dev_priv);
+       mutex_lock(&slpc->lock);
+
+       slpc_set_param(slpc,
+                      SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+                      intel_gpu_freq(dev_priv, val));
+       slpc_set_param(slpc,
+                      SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ,
+                      intel_gpu_freq(dev_priv, val));
+
+       host2guc_slpc_reset(slpc);
+       slpc->min_unslice_freq = val;
+
        mutex_unlock(&slpc->lock);
+       intel_runtime_pm_put(dev_priv);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_guc_slpc.h 
b/drivers/gpu/drm/i915/intel_guc_slpc.h
index 87b504d..51189b3 100644
--- a/drivers/gpu/drm/i915/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/intel_guc_slpc.h
@@ -12,6 +12,10 @@ struct intel_guc_slpc {
        /* Protects access to vma and SLPC actions */
        struct mutex lock;
        struct i915_vma *vma;
+
+       /* i915 cached SLPC frequency limits */
+       u32 min_unslice_freq;
+       u32 max_unslice_freq;
 };
 
 int intel_guc_slpc_task_control(struct intel_guc_slpc *slpc, u64 val,
@@ -21,6 +25,8 @@ int intel_guc_slpc_task_status(struct intel_guc_slpc *slpc, 
u64 *val,
 
 int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
+int intel_guc_slpc_max_freq_set(struct intel_guc_slpc *slpc, u32 val);
+int intel_guc_slpc_min_freq_set(struct intel_guc_slpc *slpc, u32 val);
 void intel_guc_slpc_handle_engine_reset(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_disable(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
-- 
2.7.4

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

Reply via email to