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@xxxxxxxxx> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx> Cc: Radoslaw Szwichtenberg <radoslaw.szwichtenberg@xxxxxxxxx> Cc: Michal Wajdeczko <michal.wajdeczko@xxxxxxxxx> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@xxxxxxxxx> Cc: Jeff McGee <jeff.mcgee@xxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx