[Intel-gfx] [PATCH v12 11/17] drm/i915/guc/slpc: Add support for sysfs min/max frequency control
Sagar Arun Kamble
sagar.a.kamble at intel.com
Fri Mar 30 08:31:56 UTC 2018
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.kamble at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Cc: Radoslaw Szwichtenberg <radoslaw.szwichtenberg at intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: Sujaritha Sundaresan <sujaritha.sundaresan at intel.com>
Cc: Jeff McGee <jeff.mcgee at 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
More information about the Intel-gfx
mailing list