Skip to content

Commit e059c18

Browse files
huangruirafaeljw
authored andcommitted
cpufreq: amd-pstate: Introduce the support for the processors with shared memory solution
In some of Zen2 and Zen3 based processors, they are using the shared memory that exposed from ACPI SBIOS. In this kind of the processors, there is no MSR support, so we add acpi cppc function as the backend for them. It is using a module param (shared_mem) to enable related processors manually. We will enable this by default once we address performance issue on this solution. Signed-off-by: Jinzhou Su <[email protected]> Signed-off-by: Huang Rui <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 1d215f0 commit e059c18

File tree

1 file changed

+97
-8
lines changed

1 file changed

+97
-8
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@
4848
#define AMD_PSTATE_TRANSITION_LATENCY 0x20000
4949
#define AMD_PSTATE_TRANSITION_DELAY 500
5050

51+
/*
52+
* TODO: We need more time to fine tune processors with shared memory solution
53+
* with community together.
54+
*
55+
* There are some performance drops on the CPU benchmarks which reports from
56+
* Suse. We are co-working with them to fine tune the shared memory solution. So
57+
* we disable it by default to go acpi-cpufreq on these processors and add a
58+
* module parameter to be able to enable it manually for debugging.
59+
*/
60+
static bool shared_mem = false;
61+
module_param(shared_mem, bool, 0444);
62+
MODULE_PARM_DESC(shared_mem,
63+
"enable amd-pstate on processors with shared memory solution (false = disabled (default), true = enabled)");
64+
5165
static struct cpufreq_driver amd_pstate_driver;
5266

5367
/**
@@ -85,12 +99,32 @@ struct amd_cpudata {
8599
u32 lowest_nonlinear_freq;
86100
};
87101

88-
static inline int amd_pstate_enable(bool enable)
102+
static inline int pstate_enable(bool enable)
89103
{
90104
return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable);
91105
}
92106

93-
static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
107+
static int cppc_enable(bool enable)
108+
{
109+
int cpu, ret = 0;
110+
111+
for_each_present_cpu(cpu) {
112+
ret = cppc_set_enable(cpu, enable);
113+
if (ret)
114+
return ret;
115+
}
116+
117+
return ret;
118+
}
119+
120+
DEFINE_STATIC_CALL(amd_pstate_enable, pstate_enable);
121+
122+
static inline int amd_pstate_enable(bool enable)
123+
{
124+
return static_call(amd_pstate_enable)(enable);
125+
}
126+
127+
static int pstate_init_perf(struct amd_cpudata *cpudata)
94128
{
95129
u64 cap1;
96130

@@ -113,8 +147,33 @@ static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
113147
return 0;
114148
}
115149

116-
static void amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
117-
u32 des_perf, u32 max_perf, bool fast_switch)
150+
static int cppc_init_perf(struct amd_cpudata *cpudata)
151+
{
152+
struct cppc_perf_caps cppc_perf;
153+
154+
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
155+
if (ret)
156+
return ret;
157+
158+
WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
159+
160+
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
161+
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
162+
cppc_perf.lowest_nonlinear_perf);
163+
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
164+
165+
return 0;
166+
}
167+
168+
DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
169+
170+
static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata)
171+
{
172+
return static_call(amd_pstate_init_perf)(cpudata);
173+
}
174+
175+
static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
176+
u32 des_perf, u32 max_perf, bool fast_switch)
118177
{
119178
if (fast_switch)
120179
wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached));
@@ -123,6 +182,29 @@ static void amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
123182
READ_ONCE(cpudata->cppc_req_cached));
124183
}
125184

185+
static void cppc_update_perf(struct amd_cpudata *cpudata,
186+
u32 min_perf, u32 des_perf,
187+
u32 max_perf, bool fast_switch)
188+
{
189+
struct cppc_perf_ctrls perf_ctrls;
190+
191+
perf_ctrls.max_perf = max_perf;
192+
perf_ctrls.min_perf = min_perf;
193+
perf_ctrls.desired_perf = des_perf;
194+
195+
cppc_set_perf(cpudata->cpu, &perf_ctrls);
196+
}
197+
198+
DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf);
199+
200+
static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
201+
u32 min_perf, u32 des_perf,
202+
u32 max_perf, bool fast_switch)
203+
{
204+
static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf,
205+
max_perf, fast_switch);
206+
}
207+
126208
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
127209
u32 des_perf, u32 max_perf, bool fast_switch)
128210
{
@@ -332,7 +414,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
332414
/* It will be updated by governor */
333415
policy->cur = policy->cpuinfo.min_freq;
334416

335-
policy->fast_switch_possible = true;
417+
if (boot_cpu_has(X86_FEATURE_CPPC))
418+
policy->fast_switch_possible = true;
336419

337420
/* Initial processor data capability frequencies */
338421
cpudata->max_freq = max_freq;
@@ -364,7 +447,6 @@ static struct cpufreq_driver amd_pstate_driver = {
364447
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
365448
.verify = amd_pstate_verify,
366449
.target = amd_pstate_target,
367-
.adjust_perf = amd_pstate_adjust_perf,
368450
.init = amd_pstate_cpu_init,
369451
.exit = amd_pstate_cpu_exit,
370452
.name = "amd-pstate",
@@ -387,8 +469,15 @@ static int __init amd_pstate_init(void)
387469
return -EEXIST;
388470

389471
/* capability check */
390-
if (!boot_cpu_has(X86_FEATURE_CPPC)) {
391-
pr_debug("AMD CPPC MSR based functionality is not supported\n");
472+
if (boot_cpu_has(X86_FEATURE_CPPC)) {
473+
pr_debug("AMD CPPC MSR based functionality is supported\n");
474+
amd_pstate_driver.adjust_perf = amd_pstate_adjust_perf;
475+
} else if (shared_mem) {
476+
static_call_update(amd_pstate_enable, cppc_enable);
477+
static_call_update(amd_pstate_init_perf, cppc_init_perf);
478+
static_call_update(amd_pstate_update_perf, cppc_update_perf);
479+
} else {
480+
pr_info("This processor supports shared memory solution, you can enable it with amd_pstate.shared_mem=1\n");
392481
return -ENODEV;
393482
}
394483

0 commit comments

Comments
 (0)