Message ID | cover.1718787627.git.perry.yuan@amd.com |
---|---|
Headers | show |
Series | AMD Pstate Driver Core Performance Boost | expand |
On 6/19/2024 04:16, Perry Yuan wrote: > From: Perry Yuan <Perry.Yuan@amd.com> > > With this new sysfs entry `cpb_boost`created, user can change CPU boost > state dynamically under `active`, `guided` and `passive` modes. > And the highest perf and frequency will also be updated as the boost > state changing. s/changing/changes/ > > 0): check current boost state > cat /sys/devices/system/cpu/amd_pstate/cpb_boost > > 1): disable CPU boost > sudo bash -c "echo 0 > /sys/devices/system/cpu/amd_pstate/cpb_boost" > > 2): enable CPU boost > sudo bash -c "echo 1 > /sys/devices/system/cpu/amd_pstate/cpb_boost" > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217931 > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217618 > Signed-off-by: Perry Yuan <Perry.Yuan@amd.com> > --- > drivers/cpufreq/amd-pstate-ut.c | 2 +- > drivers/cpufreq/amd-pstate.c | 112 +++++++++++++++++++++++++++++++- > drivers/cpufreq/amd-pstate.h | 1 + > 3 files changed, 113 insertions(+), 2 deletions(-) > > diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c > index fc275d41d51e..b528f198f4c3 100644 > --- a/drivers/cpufreq/amd-pstate-ut.c > +++ b/drivers/cpufreq/amd-pstate-ut.c > @@ -227,7 +227,7 @@ static void amd_pstate_ut_check_freq(u32 index) > goto skip_test; > } > > - if (cpudata->boost_supported) { > + if (amd_pstate_global_params.cpb_boost) { > if ((policy->max == cpudata->max_freq) || > (policy->max == cpudata->nominal_freq)) > amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; > diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c > index 0c50b8ba16b6..1c2320808ae1 100644 > --- a/drivers/cpufreq/amd-pstate.c > +++ b/drivers/cpufreq/amd-pstate.c > @@ -104,6 +104,7 @@ static bool amd_pstate_prefcore = true; > static struct quirk_entry *quirks; > struct amd_pstate_global_params amd_pstate_global_params; > EXPORT_SYMBOL_GPL(amd_pstate_global_params); > +static int amd_pstate_cpu_boost(int cpu, bool state); > > /* > * AMD Energy Preference Performance (EPP) > @@ -736,6 +737,7 @@ static int amd_pstate_boost_set(struct amd_cpudata *cpudata) > if (amd_pstate_global_params.cpb_supported) { > current_pstate_driver->boost_enabled = true; > WRITE_ONCE(cpudata->boost_supported, true); > + WRITE_ONCE(cpudata->boost_state, true); > } > > amd_pstate_global_params.cpb_boost = amd_pstate_global_params.cpb_supported; > @@ -743,6 +745,7 @@ static int amd_pstate_boost_set(struct amd_cpudata *cpudata) > > exit_err: > WRITE_ONCE(cpudata->boost_supported, false); > + WRITE_ONCE(cpudata->boost_state, false); > current_pstate_driver->boost_enabled = false; > amd_pstate_global_params.cpb_boost = false; > return ret; > @@ -1346,6 +1349,111 @@ static ssize_t prefcore_show(struct device *dev, > return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore)); > } > > +static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on) > +{ > + struct amd_cpudata *cpudata = policy->driver_data; > + struct cppc_perf_ctrls perf_ctrls; > + u32 highest_perf, nominal_perf, nominal_freq, max_freq; > + int ret; > + > + highest_perf = READ_ONCE(cpudata->highest_perf); > + nominal_perf = READ_ONCE(cpudata->nominal_perf); > + nominal_freq = READ_ONCE(cpudata->nominal_freq); > + max_freq = READ_ONCE(cpudata->max_freq); > + > + if (boot_cpu_has(X86_FEATURE_CPPC)) { > + u64 value = READ_ONCE(cpudata->cppc_req_cached); > + > + value &= ~GENMASK_ULL(7, 0); > + value |= on ? highest_perf : nominal_perf; > + WRITE_ONCE(cpudata->cppc_req_cached, value); > + > + wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); > + } else { > + perf_ctrls.max_perf = on ? highest_perf : nominal_perf; > + ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); > + if (ret) { > + cpufreq_cpu_release(policy); > + pr_debug("failed to set energy perf value (%d)\n", ret); > + return ret; > + } > + } > + > + if (on) > + policy->cpuinfo.max_freq = max_freq; > + else > + policy->cpuinfo.max_freq = nominal_freq * 1000; > + > + policy->max = policy->cpuinfo.max_freq; > + > + if (cppc_state == AMD_PSTATE_PASSIVE) { > + ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq); > + if (ret < 0) > + pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu); > + } > + > + return ret < 0 ? ret : 0; > +} > + > +static int amd_pstate_cpu_boost(int cpu, bool state) > +{ > + int ret; > + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); > + struct amd_cpudata *cpudata = policy->driver_data; > + > + if (!policy) { > + pr_err("policy is NULL\n"); > + ret = -ENODATA; > + goto err_exit; > + } > + > + ret = amd_pstate_cpu_boost_update(policy, state); > + refresh_frequency_limits(policy); > + WRITE_ONCE(cpudata->boost_state, state); > + policy->boost_enabled = state; > + > +err_exit: > + cpufreq_cpu_put(policy); > + return ret < 0 ? ret : 0; > +} > + > +static ssize_t cpb_boost_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + return sysfs_emit(buf, "%u\n", amd_pstate_global_params.cpb_boost); > +} It is incongruent that this returns a 0/1 but prefcore returns enabled/disabled using str_enabled_disabled(). Can we make this consistent and alos use str_enabled_disabled() please? > + > +static ssize_t cpb_boost_store(struct device *dev, struct device_attribute *b, > + const char *buf, size_t count) > +{ > + bool new_state; > + ssize_t ret; > + int cpu; > + > + if (!amd_pstate_global_params.cpb_supported) { > + pr_err("Boost mode is not supported by this processor or SBIOS\n"); > + return -EINVAL; > + } > + > + ret = kstrtobool(buf, &new_state); > + if (ret) > + return ret; > + > + mutex_lock(&amd_pstate_driver_lock); > + for_each_present_cpu(cpu) { > + ret = amd_pstate_cpu_boost(cpu, new_state); > + if (ret < 0) { > + pr_warn("failed to update cpu boost for CPU%d (%zd)\n", cpu, ret); > + goto err_exit; > + } > + } > + amd_pstate_global_params.cpb_boost = !!new_state; > + > +err_exit: > + mutex_unlock(&amd_pstate_driver_lock); > + return ret < 0 ? ret : count; > +} > + > cpufreq_freq_attr_ro(amd_pstate_max_freq); > cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); > > @@ -1356,6 +1464,7 @@ cpufreq_freq_attr_rw(energy_performance_preference); > cpufreq_freq_attr_ro(energy_performance_available_preferences); > static DEVICE_ATTR_RW(status); > static DEVICE_ATTR_RO(prefcore); > +static DEVICE_ATTR_RW(cpb_boost); > > static struct freq_attr *amd_pstate_attr[] = { > &amd_pstate_max_freq, > @@ -1380,6 +1489,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = { > static struct attribute *pstate_global_attributes[] = { > &dev_attr_status.attr, > &dev_attr_prefcore.attr, > + &dev_attr_cpb_boost.attr, > NULL > }; > > @@ -1418,7 +1528,7 @@ static int amd_pstate_init_boost(struct cpufreq_policy *policy) > if (ret) > return ret; > > - policy->boost_enabled = READ_ONCE(cpudata->boost_supported); > + policy->boost_enabled = READ_ONCE(cpudata->boost_state); > > return 0; > } > diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h > index 133042370a8f..fb240a870289 100644 > --- a/drivers/cpufreq/amd-pstate.h > +++ b/drivers/cpufreq/amd-pstate.h > @@ -100,6 +100,7 @@ struct amd_cpudata { > u64 cppc_cap1_cached; > bool suspended; > s16 epp_default; > + bool boost_state; > }; > > /**
On 6/19/2024 04:16, Perry Yuan wrote: > From: Perry Yuan <Perry.Yuan@amd.com> > > Introduce AMD CPU frequency boosting control sysfs entry which used for > switching boost on and boost off. > > If core performance boost is disabled while a core is in a boosted P-state, > the core automatically transitions to the highest performance non-boosted P-state > The highest perf and frequency will be limited by the setting value. > > Signed-off-by: Perry Yuan <Perry.Yuan@amd.com> > Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> > --- > Documentation/admin-guide/pm/amd-pstate.rst | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst > index 1e0d101b020a..bcc0d9404c18 100644 > --- a/Documentation/admin-guide/pm/amd-pstate.rst > +++ b/Documentation/admin-guide/pm/amd-pstate.rst > @@ -440,6 +440,16 @@ control its functionality at the system level. They are located in the > This attribute is read-only to check the state of preferred core set > by the kernel parameter. > > +``cpb_boost`` > + Specifies whether core performance boost is requested to be enabled or disabled > + If core performance boost is disabled while a core is in a boosted P-state, the > + core automatically transitions to the highest performance non-boosted P-state. > + AMD Core Performance Boost(CPB) is controlled by this attribute file which allows > + user to change all cores frequency boosting state. It supports all amd-pstate modes. > + > + "0" Disable Core Performance Boosting > + "1" Enable Core Performance Boosting > + Please switch to disabled/enabled as suggested in patch 5. > ``cpupower`` tool support for ``amd-pstate`` > =============================================== >
Perry Yuan <perry.yuan@amd.com> writes: > Update the cpufreq store function to use kstrtobool for parsing boolean > values. This simplifies the code and improves readability by using a > standard kernel function for boolean string conversion. > > Signed-off-by: Perry Yuan <perry.yuan@amd.com> > Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com> > --- > drivers/cpufreq/cpufreq.c | 11 +++++------ > 1 file changed, 5 insertions(+), 6 deletions(-) > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > index a45aac17c20f..1fdabb660231 100644 > --- a/drivers/cpufreq/cpufreq.c > +++ b/drivers/cpufreq/cpufreq.c > @@ -614,10 +614,9 @@ static ssize_t show_boost(struct kobject *kobj, > static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, > const char *buf, size_t count) > { > - int ret, enable; > + bool enable; > > - ret = sscanf(buf, "%d", &enable); > - if (ret != 1 || enable < 0 || enable > 1) > + if (kstrtobool(buf, &enable)) > return -EINVAL; > > if (cpufreq_boost_trigger_state(enable)) { > @@ -641,10 +640,10 @@ static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) > static ssize_t store_local_boost(struct cpufreq_policy *policy, > const char *buf, size_t count) > { > - int ret, enable; > + int ret; > + bool enable; > > - ret = kstrtoint(buf, 10, &enable); > - if (ret || enable < 0 || enable > 1) > + if (kstrtobool(buf, &enable)) > return -EINVAL; > > if (!cpufreq_driver->boost_enabled) > -- > 2.34.1
Mario Limonciello <mario.limonciello@amd.com> writes: > On 6/19/2024 04:16, Perry Yuan wrote: >> From: Perry Yuan <Perry.Yuan@amd.com> >> >> With this new sysfs entry `cpb_boost`created, user can change CPU boost >> state dynamically under `active`, `guided` and `passive` modes. >> And the highest perf and frequency will also be updated as the boost >> state changing. > > s/changing/changes/ > >> >> 0): check current boost state >> cat /sys/devices/system/cpu/amd_pstate/cpb_boost >> >> 1): disable CPU boost >> sudo bash -c "echo 0 > /sys/devices/system/cpu/amd_pstate/cpb_boost" >> >> 2): enable CPU boost >> sudo bash -c "echo 1 > /sys/devices/system/cpu/amd_pstate/cpb_boost"