Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit c8c68c3

Browse files
Perry Yuansuperm1
authored andcommitted
cpufreq: amd-pstate: initialize core precision boost state
The "Core Performance Boost (CPB) feature, when enabled in the BIOS, allows the OS to control the highest performance for each individual core. The active, passive and the guided modes of the amd-pstate driver do support controlling the core frequency boost when this BIOS feature is enabled. Additionally, the amd-pstate driver provides a sysfs interface allowing the user to activate/deactivate this core performance boost feature at runtime. Add support for the set_boost callback in the active mode driver to enable boost control via the cpufreq core. This ensures a consistent boost control interface across all pstate modes, including passive mode, guided mode, and active mode. With this addition, all three pstate modes can support the same boost control interface with unique interface and global CPB control. Each CPU also supports individual boost control, allowing global CPB to change all cores' boost states simultaneously. Specific CPUs can update their boost states separately, ensuring all cores' boost states are synchronized. Cc: Oleksandr Natalenko <oleksandr@natalenko.name> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217931 Signed-off-by: Perry Yuan <Perry.Yuan@amd.com> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com> Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com> Link: https://lore.kernel.org/r/20240626042733.3747-3-mario.limonciello@amd.com Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
1 parent 4f460bf commit c8c68c3

File tree

2 files changed

+96
-22
lines changed

2 files changed

+96
-22
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -679,43 +679,105 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
679679
cpufreq_cpu_put(policy);
680680
}
681681

682-
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
682+
static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
683683
{
684684
struct amd_cpudata *cpudata = policy->driver_data;
685+
struct cppc_perf_ctrls perf_ctrls;
686+
u32 highest_perf, nominal_perf, nominal_freq, max_freq;
685687
int ret;
686688

687-
if (!cpudata->boost_supported) {
688-
pr_err("Boost mode is not supported by this processor or SBIOS\n");
689-
return -EINVAL;
689+
highest_perf = READ_ONCE(cpudata->highest_perf);
690+
nominal_perf = READ_ONCE(cpudata->nominal_perf);
691+
nominal_freq = READ_ONCE(cpudata->nominal_freq);
692+
max_freq = READ_ONCE(cpudata->max_freq);
693+
694+
if (boot_cpu_has(X86_FEATURE_CPPC)) {
695+
u64 value = READ_ONCE(cpudata->cppc_req_cached);
696+
697+
value &= ~GENMASK_ULL(7, 0);
698+
value |= on ? highest_perf : nominal_perf;
699+
WRITE_ONCE(cpudata->cppc_req_cached, value);
700+
701+
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
702+
} else {
703+
perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
704+
ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
705+
if (ret) {
706+
cpufreq_cpu_release(policy);
707+
pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
708+
cpudata->cpu, ret);
709+
return ret;
710+
}
690711
}
691712

692-
if (state)
693-
policy->cpuinfo.max_freq = cpudata->max_freq;
694-
else
695-
policy->cpuinfo.max_freq = cpudata->nominal_freq * 1000;
713+
if (on)
714+
policy->cpuinfo.max_freq = max_freq;
715+
else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
716+
policy->cpuinfo.max_freq = nominal_freq * 1000;
696717

697718
policy->max = policy->cpuinfo.max_freq;
698719

699-
ret = freq_qos_update_request(&cpudata->req[1],
700-
policy->cpuinfo.max_freq);
701-
if (ret < 0)
702-
return ret;
720+
if (cppc_state == AMD_PSTATE_PASSIVE) {
721+
ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
722+
if (ret < 0)
723+
pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu);
724+
}
703725

704-
return 0;
726+
return ret < 0 ? ret : 0;
705727
}
706728

707-
static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
729+
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
708730
{
709-
u32 highest_perf, nominal_perf;
731+
struct amd_cpudata *cpudata = policy->driver_data;
732+
int ret;
710733

711-
highest_perf = READ_ONCE(cpudata->highest_perf);
712-
nominal_perf = READ_ONCE(cpudata->nominal_perf);
734+
if (!cpudata->boost_supported) {
735+
pr_err("Boost mode is not supported by this processor or SBIOS\n");
736+
return -EOPNOTSUPP;
737+
}
738+
mutex_lock(&amd_pstate_driver_lock);
739+
ret = amd_pstate_cpu_boost_update(policy, state);
740+
WRITE_ONCE(cpudata->boost_state, !ret ? state : false);
741+
policy->boost_enabled = !ret ? state : false;
742+
refresh_frequency_limits(policy);
743+
mutex_unlock(&amd_pstate_driver_lock);
713744

714-
if (highest_perf <= nominal_perf)
715-
return;
745+
return ret;
746+
}
716747

717-
cpudata->boost_supported = true;
748+
static int amd_pstate_init_boost_support(struct amd_cpudata *cpudata)
749+
{
750+
u64 boost_val;
751+
int ret = -1;
752+
753+
/*
754+
* If platform has no CPB support or disable it, initialize current driver
755+
* boost_enabled state to be false, it is not an error for cpufreq core to handle.
756+
*/
757+
if (!cpu_feature_enabled(X86_FEATURE_CPB)) {
758+
pr_debug_once("Boost CPB capabilities not present in the processor\n");
759+
ret = 0;
760+
goto exit_err;
761+
}
762+
763+
/* at least one CPU supports CPB, even if others fail later on to set up */
718764
current_pstate_driver->boost_enabled = true;
765+
766+
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_K7_HWCR, &boost_val);
767+
if (ret) {
768+
pr_err_once("failed to read initial CPU boost state!\n");
769+
ret = -EIO;
770+
goto exit_err;
771+
}
772+
773+
if (!(boost_val & MSR_K7_HWCR_CPB_DIS))
774+
cpudata->boost_supported = true;
775+
776+
return 0;
777+
778+
exit_err:
779+
cpudata->boost_supported = false;
780+
return ret;
719781
}
720782

721783
static void amd_perf_ctl_reset(unsigned int cpu)
@@ -968,6 +1030,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
9681030
if (ret)
9691031
goto free_cpudata1;
9701032

1033+
ret = amd_pstate_init_boost_support(cpudata);
1034+
if (ret)
1035+
goto free_cpudata1;
1036+
9711037
min_freq = READ_ONCE(cpudata->min_freq);
9721038
max_freq = READ_ONCE(cpudata->max_freq);
9731039

@@ -980,6 +1046,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
9801046
policy->cpuinfo.min_freq = min_freq;
9811047
policy->cpuinfo.max_freq = max_freq;
9821048

1049+
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
1050+
9831051
/* It will be updated by governor */
9841052
policy->cur = policy->cpuinfo.min_freq;
9851053

@@ -1005,7 +1073,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10051073

10061074
policy->driver_data = cpudata;
10071075

1008-
amd_pstate_boost_init(cpudata);
10091076
if (!current_pstate_driver->adjust_perf)
10101077
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
10111078

@@ -1420,6 +1487,10 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14201487
if (ret)
14211488
goto free_cpudata1;
14221489

1490+
ret = amd_pstate_init_boost_support(cpudata);
1491+
if (ret)
1492+
goto free_cpudata1;
1493+
14231494
min_freq = READ_ONCE(cpudata->min_freq);
14241495
max_freq = READ_ONCE(cpudata->max_freq);
14251496

@@ -1435,6 +1506,8 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14351506
policy->min = policy->cpuinfo.min_freq;
14361507
policy->max = policy->cpuinfo.max_freq;
14371508

1509+
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
1510+
14381511
/*
14391512
* Set the policy to provide a valid fallback value in case
14401513
* the default cpufreq governor is neither powersave nor performance.
@@ -1456,7 +1529,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14561529
return ret;
14571530
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
14581531
}
1459-
amd_pstate_boost_init(cpudata);
14601532

14611533
return 0;
14621534

@@ -1718,6 +1790,7 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
17181790
.suspend = amd_pstate_epp_suspend,
17191791
.resume = amd_pstate_epp_resume,
17201792
.update_limits = amd_pstate_update_limits,
1793+
.set_boost = amd_pstate_set_boost,
17211794
.name = "amd-pstate-epp",
17221795
.attr = amd_pstate_epp_attr,
17231796
};

drivers/cpufreq/amd-pstate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct amd_cpudata {
100100
u64 cppc_cap1_cached;
101101
bool suspended;
102102
s16 epp_default;
103+
bool boost_state;
103104
};
104105

105106
#endif /* _LINUX_AMD_PSTATE_H */

0 commit comments

Comments
 (0)