cpufreq: amd_pstate: Fix initial highest_perf value
Subsystems (2)
Perry Yuan
reviewerPATCH v2 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.54--- 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
Quoted 18 lines · Perry
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_CAP1andcppc_acpiinterface firstly, then compare with the highest perf value got by callingamd_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.54
Quoted 2 lines
Fixes 3743d55b289c2 (x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations)Signed-off-by Perry Yuan <[email protected]>
Quoted 51 lines
--- 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
Quoted 18 lines · Perry
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_CAP1andcppc_acpiinterface firstly, then compare with the highest perf value got by callingamd_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.54
Quoted 2 lines
Fixes 3743d55b289c2 (x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations)Signed-off-by Perry Yuan <[email protected]>
Quoted 51 lines
--- 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