Commit ad4caad5 authored by Mario Limonciello's avatar Mario Limonciello

cpufreq: amd-pstate: Merge amd_pstate_highest_perf_set() into amd_get_boost_ratio_numerator()

The special case in amd_pstate_highest_perf_set() is the value used
for calculating the boost numerator.  Merge this into
amd_get_boost_ratio_numerator() and then use that to calculate boost
ratio.

This allows dropping more special casing of the highest perf value.
Reviewed-by: default avatarGautham R. Shenoy <gautham.shenoy@amd.com>
Signed-off-by: default avatarMario Limonciello <mario.limonciello@amd.com>
parent 279f838a
...@@ -251,7 +251,8 @@ performance supported in `AMD CPPC Performance Capability <perf_cap_>`_). ...@@ -251,7 +251,8 @@ performance supported in `AMD CPPC Performance Capability <perf_cap_>`_).
In some ASICs, the highest CPPC performance is not the one in the ``_CPC`` In some ASICs, the highest CPPC performance is not the one in the ``_CPC``
table, so we need to expose it to sysfs. If boost is not active, but table, so we need to expose it to sysfs. If boost is not active, but
still supported, this maximum frequency will be larger than the one in still supported, this maximum frequency will be larger than the one in
``cpuinfo``. ``cpuinfo``. On systems that support preferred core, the driver will have
different values for some cores than others.
This attribute is read-only. This attribute is read-only.
``amd_pstate_lowest_nonlinear_freq`` ``amd_pstate_lowest_nonlinear_freq``
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/topology.h> #include <asm/topology.h>
#define CPPC_HIGHEST_PERF_PERFORMANCE 196
#define CPPC_HIGHEST_PERF_PREFCORE 166 #define CPPC_HIGHEST_PERF_PREFCORE 166
enum amd_pref_core { enum amd_pref_core {
...@@ -245,6 +246,21 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) ...@@ -245,6 +246,21 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
*numerator = boost_numerator; *numerator = boost_numerator;
return 0; return 0;
} }
/*
* For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
* the highest performance level is set to 196.
* https://bugzilla.kernel.org/show_bug.cgi?id=218759
*/
if (cpu_feature_enabled(X86_FEATURE_ZEN4)) {
switch (boot_cpu_data.x86_model) {
case 0x70 ... 0x7f:
*numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
return 0;
default:
break;
}
}
*numerator = CPPC_HIGHEST_PERF_PREFCORE; *numerator = CPPC_HIGHEST_PERF_PREFCORE;
return 0; return 0;
......
...@@ -52,8 +52,6 @@ ...@@ -52,8 +52,6 @@
#define AMD_PSTATE_TRANSITION_LATENCY 20000 #define AMD_PSTATE_TRANSITION_LATENCY 20000
#define AMD_PSTATE_TRANSITION_DELAY 1000 #define AMD_PSTATE_TRANSITION_DELAY 1000
#define AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY 600 #define AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY 600
#define CPPC_HIGHEST_PERF_PERFORMANCE 196
#define CPPC_HIGHEST_PERF_DEFAULT 166
#define AMD_CPPC_EPP_PERFORMANCE 0x00 #define AMD_CPPC_EPP_PERFORMANCE 0x00
#define AMD_CPPC_EPP_BALANCE_PERFORMANCE 0x80 #define AMD_CPPC_EPP_BALANCE_PERFORMANCE 0x80
...@@ -372,43 +370,17 @@ static inline int amd_pstate_enable(bool enable) ...@@ -372,43 +370,17 @@ static inline int amd_pstate_enable(bool enable)
return static_call(amd_pstate_enable)(enable); return static_call(amd_pstate_enable)(enable);
} }
static u32 amd_pstate_highest_perf_set(struct amd_cpudata *cpudata)
{
struct cpuinfo_x86 *c = &cpu_data(0);
/*
* For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
* the highest performance level is set to 196.
* https://bugzilla.kernel.org/show_bug.cgi?id=218759
*/
if (c->x86 == 0x19 && (c->x86_model >= 0x70 && c->x86_model <= 0x7f))
return CPPC_HIGHEST_PERF_PERFORMANCE;
return CPPC_HIGHEST_PERF_DEFAULT;
}
static int pstate_init_perf(struct amd_cpudata *cpudata) static int pstate_init_perf(struct amd_cpudata *cpudata)
{ {
u64 cap1; u64 cap1;
u32 highest_perf;
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1, int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
&cap1); &cap1);
if (ret) if (ret)
return ret; return ret;
/* For platforms that do not support the preferred core feature, the WRITE_ONCE(cpudata->highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
* highest_pef may be configured with 166 or 255, to avoid max frequency WRITE_ONCE(cpudata->max_limit_perf, AMD_CPPC_HIGHEST_PERF(cap1));
* calculated wrongly. we take the AMD_CPPC_HIGHEST_PERF(cap1) value as
* the default max perf.
*/
if (cpudata->hw_prefcore)
highest_perf = amd_pstate_highest_perf_set(cpudata);
else
highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
WRITE_ONCE(cpudata->highest_perf, highest_perf);
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1)); WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1)); WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1)); WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
...@@ -420,19 +392,13 @@ static int pstate_init_perf(struct amd_cpudata *cpudata) ...@@ -420,19 +392,13 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
static int cppc_init_perf(struct amd_cpudata *cpudata) static int cppc_init_perf(struct amd_cpudata *cpudata)
{ {
struct cppc_perf_caps cppc_perf; struct cppc_perf_caps cppc_perf;
u32 highest_perf;
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
if (ret) if (ret)
return ret; return ret;
if (cpudata->hw_prefcore) WRITE_ONCE(cpudata->highest_perf, cppc_perf.highest_perf);
highest_perf = amd_pstate_highest_perf_set(cpudata); WRITE_ONCE(cpudata->max_limit_perf, cppc_perf.highest_perf);
else
highest_perf = cppc_perf.highest_perf;
WRITE_ONCE(cpudata->highest_perf, highest_perf);
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf); WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
WRITE_ONCE(cpudata->lowest_nonlinear_perf, WRITE_ONCE(cpudata->lowest_nonlinear_perf,
cppc_perf.lowest_nonlinear_perf); cppc_perf.lowest_nonlinear_perf);
...@@ -918,8 +884,8 @@ static u32 amd_pstate_get_transition_latency(unsigned int cpu) ...@@ -918,8 +884,8 @@ static u32 amd_pstate_get_transition_latency(unsigned int cpu)
static int amd_pstate_init_freq(struct amd_cpudata *cpudata) static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
{ {
int ret; int ret;
u32 min_freq; u32 min_freq, max_freq;
u32 highest_perf, max_freq; u64 numerator;
u32 nominal_perf, nominal_freq; u32 nominal_perf, nominal_freq;
u32 lowest_nonlinear_perf, lowest_nonlinear_freq; u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
u32 boost_ratio, lowest_nonlinear_ratio; u32 boost_ratio, lowest_nonlinear_ratio;
...@@ -941,8 +907,10 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata) ...@@ -941,8 +907,10 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
nominal_perf = READ_ONCE(cpudata->nominal_perf); nominal_perf = READ_ONCE(cpudata->nominal_perf);
highest_perf = READ_ONCE(cpudata->highest_perf); ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
boost_ratio = div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf); if (ret)
return ret;
boost_ratio = div_u64(numerator << SCHED_CAPACITY_SHIFT, nominal_perf);
max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000; max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment