cpufreq: amd_pstate: Fix initial highest_perf value
Subsystems (2)
Perry Yuan
reviewerPATCH v3 1/1 cpufreq: amd_pstate: Fix initial highest_perf value
To avoid some new AMD processors use wrong highest perf when amd pstate driver loaded, this fix will query the highest perf from MSR register MSR_AMD_CPPC_CAP1 and cppc_acpi interface firstly, then compare with the highest perf value got by calling amd_get_highest_perf() function.
The lower value will be the correct highest perf we need to use. Otherwise the CPU max MHz will be incorrect if the amd_get_highest_perf() did not cover the new process family and model ID.
Like this lscpu info, the max frequency is incorrect.
Vendor ID: AuthenticAMD
Socket(s): 1
Stepping: 2
CPU max MHz: 5410.0000
CPU min MHz: 400.0000
BogoMIPS: 5600.54Fixes 3743d55b289c2 (x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations)
Acked-by Huang Rui <[email protected]>
Signed-off-by Perry Yuan <[email protected]>
--- drivers/cpufreq/amd-pstate.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/cpufreq/amd-pstate.c +12 -2
@@ -354,6 +354,7 @@ static inline int amd_pstate_enable(bool enable)static int pstate_init_perf (struct amd_cpudata *cpudata) {u64 cap1; +u32 highest_perf;int ret =rdmsrl_safe_on_cpu (cpudata->cpu,MSR_AMD_CPPC_CAP1 , &cap1);
@@ -365,7 +366,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)* * CPPC entry doesn't indicate the highest performance in some ASICs. */ -WRITE_ONCE (cpudata->highest_perf,amd_get_highest_perf ()); + highest_perf =amd_get_highest_perf (); +if (highest_perf >AMD_CPPC_HIGHEST_PERF (cap1)) + highest_perf =AMD_CPPC_HIGHEST_PERF (cap1); + +WRITE_ONCE (cpudata->highest_perf, highest_perf);WRITE_ONCE (cpudata->nominal_perf,AMD_CPPC_NOMINAL_PERF (cap1));WRITE_ONCE (cpudata->lowest_nonlinear_perf,AMD_CPPC_LOWNONLIN_PERF (cap1));
@@ -377,12 +382,17 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)static int cppc_init_perf (struct amd_cpudata *cpudata) {struct cppc_perf_caps cppc_perf; +u32 highest_perf;int ret =cppc_get_perf_caps (cpudata->cpu, &cppc_perf);if (ret)return ret; -WRITE_ONCE (cpudata->highest_perf,amd_get_highest_perf ()); + highest_perf =amd_get_highest_perf (); +if (highest_perf > cppc_perf.highest_perf) + highest_perf = cppc_perf.highest_perf; + +WRITE_ONCE (cpudata->highest_perf, highest_perf);WRITE_ONCE (cpudata->nominal_perf, cppc_perf.nominal_perf); WRITE_ONCE(cpudata->lowest_nonlinear_perf,
Signature · 1 line
2.34.1