Skip to content

Commit 279f838

Browse files
committed
x86/amd: Detect preferred cores in amd_get_boost_ratio_numerator()
AMD systems that support preferred cores will use "166" as their numerator for max frequency calculations instead of "255". Add a function for detecting preferred cores by looking at the highest perf value on all cores. If preferred cores are enabled return 166 and if disabled the value in the highest perf register. As the function will be called multiple times, cache the values for the boost numerator and if preferred cores will be enabled in global variables. Reviewed-by: Gautham R. Shenoy <[email protected]> Signed-off-by: Mario Limonciello <[email protected]>
1 parent 2819bfe commit 279f838

File tree

3 files changed

+101
-31
lines changed

3 files changed

+101
-31
lines changed

arch/x86/kernel/acpi/cppc.c

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
#include <asm/processor.h>
1010
#include <asm/topology.h>
1111

12+
#define CPPC_HIGHEST_PERF_PREFCORE 166
13+
14+
enum amd_pref_core {
15+
AMD_PREF_CORE_UNKNOWN = 0,
16+
AMD_PREF_CORE_SUPPORTED,
17+
AMD_PREF_CORE_UNSUPPORTED,
18+
};
19+
static enum amd_pref_core amd_pref_core_detected;
20+
static u64 boost_numerator;
21+
1222
/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
1323

1424
bool cpc_supported_by_cpu(void)
@@ -146,6 +156,66 @@ int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
146156
}
147157
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
148158

159+
/**
160+
* amd_detect_prefcore: Detect if CPUs in the system support preferred cores
161+
* @detected: Output variable for the result of the detection.
162+
*
163+
* Determine whether CPUs in the system support preferred cores. On systems
164+
* that support preferred cores, different highest perf values will be found
165+
* on different cores. On other systems, the highest perf value will be the
166+
* same on all cores.
167+
*
168+
* The result of the detection will be stored in the 'detected' parameter.
169+
*
170+
* Return: 0 for success, negative error code otherwise
171+
*/
172+
int amd_detect_prefcore(bool *detected)
173+
{
174+
int cpu, count = 0;
175+
u64 highest_perf[2] = {0};
176+
177+
if (WARN_ON(!detected))
178+
return -EINVAL;
179+
180+
switch (amd_pref_core_detected) {
181+
case AMD_PREF_CORE_SUPPORTED:
182+
*detected = true;
183+
return 0;
184+
case AMD_PREF_CORE_UNSUPPORTED:
185+
*detected = false;
186+
return 0;
187+
default:
188+
break;
189+
}
190+
191+
for_each_present_cpu(cpu) {
192+
u32 tmp;
193+
int ret;
194+
195+
ret = amd_get_highest_perf(cpu, &tmp);
196+
if (ret)
197+
return ret;
198+
199+
if (!count || (count == 1 && tmp != highest_perf[0]))
200+
highest_perf[count++] = tmp;
201+
202+
if (count == 2)
203+
break;
204+
}
205+
206+
*detected = (count == 2);
207+
boost_numerator = highest_perf[0];
208+
209+
amd_pref_core_detected = *detected ? AMD_PREF_CORE_SUPPORTED :
210+
AMD_PREF_CORE_UNSUPPORTED;
211+
212+
pr_debug("AMD CPPC preferred core is %ssupported (highest perf: 0x%llx)\n",
213+
*detected ? "" : "un", highest_perf[0]);
214+
215+
return 0;
216+
}
217+
EXPORT_SYMBOL_GPL(amd_detect_prefcore);
218+
149219
/**
150220
* amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
151221
* @cpu: CPU to get numerator for.
@@ -155,24 +225,27 @@ EXPORT_SYMBOL_GPL(amd_get_highest_perf);
155225
* a CPU. On systems that support preferred cores, this will be a hardcoded
156226
* value. On other systems this will the highest performance register value.
157227
*
228+
* If booting the system with amd-pstate enabled but preferred cores disabled then
229+
* the correct boost numerator will be returned to match hardware capabilities
230+
* even if the preferred cores scheduling hints are not enabled.
231+
*
158232
* Return: 0 for success, negative error code otherwise.
159233
*/
160234
int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
161235
{
162-
struct cpuinfo_x86 *c = &boot_cpu_data;
236+
bool prefcore;
237+
int ret;
163238

164-
if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
165-
(c->x86_model >= 0x70 && c->x86_model < 0x80))) {
166-
*numerator = 166;
167-
return 0;
168-
}
239+
ret = amd_detect_prefcore(&prefcore);
240+
if (ret)
241+
return ret;
169242

170-
if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
171-
(c->x86_model >= 0x40 && c->x86_model < 0x70))) {
172-
*numerator = 166;
243+
/* without preferred cores, return the highest perf register value */
244+
if (!prefcore) {
245+
*numerator = boost_numerator;
173246
return 0;
174247
}
175-
*numerator = 255;
248+
*numerator = CPPC_HIGHEST_PERF_PREFCORE;
176249

177250
return 0;
178251
}

drivers/cpufreq/amd-pstate.c

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -815,32 +815,18 @@ static DECLARE_WORK(sched_prefcore_work, amd_pstste_sched_prefcore_workfn);
815815

816816
static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
817817
{
818-
int ret, prio;
819-
u32 highest_perf;
820-
821-
ret = amd_get_highest_perf(cpudata->cpu, &highest_perf);
822-
if (ret)
818+
/* user disabled or not detected */
819+
if (!amd_pstate_prefcore)
823820
return;
824821

825822
cpudata->hw_prefcore = true;
826-
/* check if CPPC preferred core feature is enabled*/
827-
if (highest_perf < CPPC_MAX_PERF)
828-
prio = (int)highest_perf;
829-
else {
830-
pr_debug("AMD CPPC preferred core is unsupported!\n");
831-
cpudata->hw_prefcore = false;
832-
return;
833-
}
834-
835-
if (!amd_pstate_prefcore)
836-
return;
837823

838824
/*
839825
* The priorities can be set regardless of whether or not
840826
* sched_set_itmt_support(true) has been called and it is valid to
841827
* update them at any time after it has been called.
842828
*/
843-
sched_set_itmt_core_prio(prio, cpudata->cpu);
829+
sched_set_itmt_core_prio((int)READ_ONCE(cpudata->highest_perf), cpudata->cpu);
844830

845831
schedule_work(&sched_prefcore_work);
846832
}
@@ -1011,12 +997,12 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
1011997

1012998
cpudata->cpu = policy->cpu;
1013999

1014-
amd_pstate_init_prefcore(cpudata);
1015-
10161000
ret = amd_pstate_init_perf(cpudata);
10171001
if (ret)
10181002
goto free_cpudata1;
10191003

1004+
amd_pstate_init_prefcore(cpudata);
1005+
10201006
ret = amd_pstate_init_freq(cpudata);
10211007
if (ret)
10221008
goto free_cpudata1;
@@ -1466,12 +1452,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14661452
cpudata->cpu = policy->cpu;
14671453
cpudata->epp_policy = 0;
14681454

1469-
amd_pstate_init_prefcore(cpudata);
1470-
14711455
ret = amd_pstate_init_perf(cpudata);
14721456
if (ret)
14731457
goto free_cpudata1;
14741458

1459+
amd_pstate_init_prefcore(cpudata);
1460+
14751461
ret = amd_pstate_init_freq(cpudata);
14761462
if (ret)
14771463
goto free_cpudata1;
@@ -1916,6 +1902,12 @@ static int __init amd_pstate_init(void)
19161902
static_call_update(amd_pstate_update_perf, cppc_update_perf);
19171903
}
19181904

1905+
if (amd_pstate_prefcore) {
1906+
ret = amd_detect_prefcore(&amd_pstate_prefcore);
1907+
if (ret)
1908+
return ret;
1909+
}
1910+
19191911
/* enable amd pstate feature */
19201912
ret = amd_pstate_enable(true);
19211913
if (ret) {

include/acpi/cppc_acpi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ extern int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps);
161161
extern int cppc_set_auto_sel(int cpu, bool enable);
162162
extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
163163
extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
164+
extern int amd_detect_prefcore(bool *detected);
164165
#else /* !CONFIG_ACPI_CPPC_LIB */
165166
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
166167
{
@@ -242,6 +243,10 @@ static inline int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator
242243
{
243244
return -EOPNOTSUPP;
244245
}
246+
static inline int amd_detect_prefcore(bool *detected)
247+
{
248+
return -ENODEV;
249+
}
245250
#endif /* !CONFIG_ACPI_CPPC_LIB */
246251

247252
#endif /* _CPPC_ACPI_H*/

0 commit comments

Comments
 (0)