Message ID | 35464456ab468f389ff3816829647db77924a6b5.1718262992.git.perry.yuan@amd.com |
---|---|
State | Superseded |
Headers | show |
Series | AMD Pstate Driver Core Performance Boost | expand |
[AMD Official Use Only - AMD Internal Distribution Only] > -----Original Message----- > From: Limonciello, Mario <Mario.Limonciello@amd.com> > Sent: Friday, June 14, 2024 1:55 AM > To: Yuan, Perry <Perry.Yuan@amd.com>; Shenoy, Gautham Ranjal > <gautham.shenoy@amd.com>; Petkov, Borislav <Borislav.Petkov@amd.com> > Cc: rafael.j.wysocki@intel.com; viresh.kumar@linaro.org; Deucher, Alexander > <Alexander.Deucher@amd.com>; Huang, Shimmer > <Shimmer.Huang@amd.com>; Du, Xiaojian <Xiaojian.Du@amd.com>; Meng, > Li (Jassmine) <Li.Meng@amd.com>; linux-pm@vger.kernel.org; linux- > kernel@vger.kernel.org > Subject: Re: [PATCH v11 5/9] cpufreq: amd-pstate: implement cpb_boost > sysfs entry for boost control > > On 6/13/2024 02:25, 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. > > > > 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 | 117 > +++++++++++++++++++++++++++++++- > > drivers/cpufreq/amd-pstate.h | 1 + > > 3 files changed, 118 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 9f42524074a9..fe7c9d3562c5 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) @@ -738,6 +739,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; > > @@ -745,6 +747,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; > > @@ -1348,6 +1351,116 @@ 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; > > + > > + if (!policy) { > > + pr_err("policy is null\n"); > > + return -ENODATA; > > + } > > This is dead code that can't possibly be hit, because there would be a NULL > pointer dereference above for this line: > > struct amd_cpudata *cpudata = policy->driver_data; > > Furthermore, the caller for this function, amd_pstate_cpu_boost() has the > same check already. > > So drop the check here. Will improve the checking code in v12. Thanks for the feedback. > > > + > > + 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); > > +} > > + > > +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); > > > > @@ -1358,6 +1471,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, > > @@ -1382,6 +1496,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 > > }; > > > > @@ -1420,7 +1535,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 0b75a6267fca..9eba854ab7d3 > 100644 > > --- a/drivers/cpufreq/amd-pstate.h > > +++ b/drivers/cpufreq/amd-pstate.h > > @@ -99,6 +99,7 @@ struct amd_cpudata { > > u32 policy; > > u64 cppc_cap1_cached; > > bool suspended; > > + bool boost_state; > > }; > > > > /**
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 9f42524074a9..fe7c9d3562c5 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) @@ -738,6 +739,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; @@ -745,6 +747,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; @@ -1348,6 +1351,116 @@ 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; + + if (!policy) { + pr_err("policy is null\n"); + return -ENODATA; + } + + 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); +} + +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); @@ -1358,6 +1471,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, @@ -1382,6 +1496,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 }; @@ -1420,7 +1535,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 0b75a6267fca..9eba854ab7d3 100644 --- a/drivers/cpufreq/amd-pstate.h +++ b/drivers/cpufreq/amd-pstate.h @@ -99,6 +99,7 @@ struct amd_cpudata { u32 policy; u64 cppc_cap1_cached; bool suspended; + bool boost_state; }; /**