* [PATCH 1/6] Revert "ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn"
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 2/6] ACPI: Add CPPC v4 definitions Mario Limonciello (AMD)
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello, stable, Kim Phillips
Some older systems don't support CPPC in the firmware and this just makes
noise for them when booting. Drop back to debug.
This reverts commit 21fb59ab4b9767085f4fe1edbdbe3177fbb9ec97.
Cc: stable@vger.kernel.org
Fixes: 21fb59ab4b976 ("ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn")
Reported-by: Kim Phillips <kim.phillips@amd.com>
Tested-by: Kim Phillips <kim.phillips@amd.com>
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
arch/x86/kernel/acpi/cppc.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c
index d7c8ef1e354d3..be4c5e9e5ff6f 100644
--- a/arch/x86/kernel/acpi/cppc.c
+++ b/arch/x86/kernel/acpi/cppc.c
@@ -88,19 +88,19 @@ static void amd_set_max_freq_ratio(void)
rc = cppc_get_perf_caps(0, &perf_caps);
if (rc) {
- pr_warn("Could not retrieve perf counters (%d)\n", rc);
+ pr_debug("Could not retrieve perf counters (%d)\n", rc);
return;
}
rc = amd_get_boost_ratio_numerator(0, &numerator);
if (rc) {
- pr_warn("Could not retrieve highest performance (%d)\n", rc);
+ pr_debug("Could not retrieve highest performance (%d)\n", rc);
return;
}
nominal_perf = perf_caps.nominal_perf;
if (!nominal_perf) {
- pr_warn("Could not retrieve nominal performance\n");
+ pr_debug("Could not retrieve nominal performance\n");
return;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/6] ACPI: Add CPPC v4 definitions
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 1/6] Revert "ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn" Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 3/6] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello (AMD)
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
ACPI 6.6 introduced new optional package values for
`OSPMNominalPerformanceRegister` and
`ResourcePriorityRegisters`.
Add these into the defines. As they're not used right now they are not
wired up to anything at this time.
Link: https://uefi.org/specs/ACPI/6.6/08_Processor_Configuration_and_Control.html#cpc-continuous-performance-control
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/acpi/cppc_acpi.c | 16 ++++++++++++----
include/acpi/cppc_acpi.h | 13 +++++++++----
2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 2e91c5a977611..cbfebc50b6eab 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -755,14 +755,15 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
*/
if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) ||
(cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) ||
- (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) {
+ (cpc_rev == CPPC_V4_REV && num_ent != CPPC_V4_NUM_ENT) ||
+ (cpc_rev > CPPC_V4_REV && num_ent <= CPPC_V4_NUM_ENT)) {
pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n",
num_ent, pr->id);
goto out_free;
}
- if (cpc_rev > CPPC_V3_REV) {
- num_ent = CPPC_V3_NUM_ENT;
- cpc_rev = CPPC_V3_REV;
+ if (cpc_rev > CPPC_V4_REV) {
+ num_ent = CPPC_V4_NUM_ENT;
+ cpc_rev = CPPC_V4_REV;
}
cpc_ptr->num_entries = num_ent;
@@ -845,6 +846,13 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_BUFFER;
memcpy(&cpc_ptr->cpc_regs[i-2].cpc_entry.reg, gas_t, sizeof(*gas_t));
+ } else if (cpc_obj->type == ACPI_TYPE_PACKAGE) {
+ /*
+ * CPPC v4 ResourcePriorityRegisters is a Package.
+ * Store NULL for now as it's not wired up to anything.
+ */
+ cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_PACKAGE;
+ cpc_ptr->cpc_regs[i-2].cpc_entry.pkg_data = NULL;
} else {
pr_debug("Invalid entry type (%d) in _CPC for CPU:%d\n",
i, pr->id);
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
index d1f02ceec4f98..38bf9013c6e2e 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -17,16 +17,18 @@
#include <acpi/pcc.h>
#include <acpi/processor.h>
-/* CPPCv2 and CPPCv3 support */
+/* CPPC support */
#define CPPC_V2_REV 2
#define CPPC_V3_REV 3
+#define CPPC_V4_REV 4
#define CPPC_V2_NUM_ENT 21
#define CPPC_V3_NUM_ENT 23
+#define CPPC_V4_NUM_ENT 25
#define PCC_CMD_COMPLETE_MASK (1 << 0)
#define PCC_ERROR_MASK (1 << 2)
-#define MAX_CPC_REG_ENT 21
+#define MAX_CPC_REG_ENT 23
/* CPPC specific PCC commands. */
#define CMD_READ 0
@@ -60,8 +62,8 @@ struct cpc_reg {
/*
* Each entry in the CPC table is either
- * of type ACPI_TYPE_BUFFER or
- * ACPI_TYPE_INTEGER.
+ * of type ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER,
+ * or ACPI_TYPE_PACKAGE (for CPPC v4 ResourcePriorityRegisters).
*/
struct cpc_register_resource {
acpi_object_type type;
@@ -69,6 +71,7 @@ struct cpc_register_resource {
union {
struct cpc_reg reg;
u64 int_value;
+ void *pkg_data;
} cpc_entry;
};
@@ -109,6 +112,8 @@ enum cppc_regs {
REFERENCE_PERF,
LOWEST_FREQ,
NOMINAL_FREQ,
+ OSPM_NOMINAL_PERF,
+ RESOURCE_PRIO,
};
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/6] ACPI: CPPC: Add support for reading HighestFreq
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 1/6] Revert "ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn" Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 2/6] ACPI: Add CPPC v4 definitions Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 4/6] ACPI: CPPC: Refactor boost ratio handling Mario Limonciello (AMD)
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
A future revision of the ACPI specification will be including
a definition for HighestFreq. Add support for reading it.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/acpi/cppc_acpi.c | 31 +++++++++++++++++++++----------
include/acpi/cppc_acpi.h | 7 ++++++-
2 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index cbfebc50b6eab..f446ef5f7305b 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -182,6 +182,7 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, lowest_nonlinear_perf);
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, guaranteed_perf);
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, lowest_freq);
show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_freq);
+show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, highest_freq);
show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
@@ -222,6 +223,7 @@ static struct attribute *cppc_attrs[] = {
&nominal_perf.attr,
&nominal_freq.attr,
&lowest_freq.attr,
+ &highest_freq.attr,
NULL
};
ATTRIBUTE_GROUPS(cppc);
@@ -751,19 +753,20 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
/*
* Disregard _CPC if the number of entries in the return package is not
* as expected, but support future revisions being proper supersets of
- * the v3 and only causing more entries to be returned by _CPC.
+ * the v4 and only causing more entries to be returned by _CPC.
*/
if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) ||
(cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) ||
(cpc_rev == CPPC_V4_REV && num_ent != CPPC_V4_NUM_ENT) ||
- (cpc_rev > CPPC_V4_REV && num_ent <= CPPC_V4_NUM_ENT)) {
+ (cpc_rev == CPPC_V5_REV && num_ent != CPPC_V5_NUM_ENT) ||
+ (cpc_rev > CPPC_V5_REV && num_ent <= CPPC_V5_NUM_ENT)) {
pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n",
num_ent, pr->id);
goto out_free;
}
- if (cpc_rev > CPPC_V4_REV) {
- num_ent = CPPC_V4_NUM_ENT;
- cpc_rev = CPPC_V4_REV;
+ if (cpc_rev > CPPC_V5_REV) {
+ num_ent = CPPC_V5_NUM_ENT;
+ cpc_rev = CPPC_V5_REV;
}
cpc_ptr->num_entries = num_ent;
@@ -1361,9 +1364,10 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
struct cpc_register_resource *highest_reg, *lowest_reg,
*lowest_non_linear_reg, *nominal_reg, *reference_reg,
- *guaranteed_reg, *low_freq_reg = NULL, *nom_freq_reg = NULL;
+ *guaranteed_reg, *low_freq_reg = NULL, *nom_freq_reg = NULL,
+ *highest_freq_reg = NULL;
u64 high, low, guaranteed, nom, ref, min_nonlinear,
- low_f = 0, nom_f = 0;
+ low_f = 0, nom_f = 0, high_f = 0;
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
struct cppc_pcc_data *pcc_ss_data = NULL;
int ret = 0, regs_in_pcc = 0;
@@ -1380,6 +1384,7 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
reference_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
low_freq_reg = &cpc_desc->cpc_regs[LOWEST_FREQ];
nom_freq_reg = &cpc_desc->cpc_regs[NOMINAL_FREQ];
+ highest_freq_reg = &cpc_desc->cpc_regs[HIGHEST_FREQ];
guaranteed_reg = &cpc_desc->cpc_regs[GUARANTEED_PERF];
/* Are any of the regs PCC ?*/
@@ -1387,7 +1392,7 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) ||
(CPC_SUPPORTED(reference_reg) && CPC_IN_PCC(reference_reg)) ||
CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg) ||
- CPC_IN_PCC(guaranteed_reg)) {
+ CPC_IN_PCC(guaranteed_reg) || CPC_IN_PCC(highest_freq_reg)) {
if (pcc_ss_id < 0) {
pr_debug("Invalid pcc_ss_id\n");
return -ENODEV;
@@ -1450,7 +1455,7 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
goto out_err;
}
- /* Read optional lowest and nominal frequencies if present */
+ /* Read optional lowest, highest and nominal frequencies if present */
if (CPC_SUPPORTED(low_freq_reg)) {
ret = cpc_read(cpunum, low_freq_reg, &low_f);
if (ret)
@@ -1463,9 +1468,15 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
goto out_err;
}
+ if (CPC_SUPPORTED(highest_freq_reg)) {
+ ret = cpc_read(cpunum, highest_freq_reg, &high_f);
+ if (ret)
+ goto out_err;
+ }
+
perf_caps->lowest_freq = low_f;
perf_caps->nominal_freq = nom_f;
-
+ perf_caps->highest_freq = high_f;
out_err:
if (regs_in_pcc)
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
index 38bf9013c6e2e..79f1eef957a45 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -21,14 +21,16 @@
#define CPPC_V2_REV 2
#define CPPC_V3_REV 3
#define CPPC_V4_REV 4
+#define CPPC_V5_REV 5
#define CPPC_V2_NUM_ENT 21
#define CPPC_V3_NUM_ENT 23
#define CPPC_V4_NUM_ENT 25
+#define CPPC_V5_NUM_ENT 27
#define PCC_CMD_COMPLETE_MASK (1 << 0)
#define PCC_ERROR_MASK (1 << 2)
-#define MAX_CPC_REG_ENT 23
+#define MAX_CPC_REG_ENT 25
/* CPPC specific PCC commands. */
#define CMD_READ 0
@@ -114,6 +116,8 @@ enum cppc_regs {
NOMINAL_FREQ,
OSPM_NOMINAL_PERF,
RESOURCE_PRIO,
+ HIGHEST_FREQ,
+ CURRENT_FREQ,
};
/*
@@ -131,6 +135,7 @@ struct cppc_perf_caps {
u32 lowest_nonlinear_perf;
u32 lowest_freq;
u32 nominal_freq;
+ u32 highest_freq;
};
struct cppc_perf_ctrls {
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/6] ACPI: CPPC: Refactor boost ratio handling
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
` (2 preceding siblings ...)
2026-04-27 3:55 ` [PATCH 3/6] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 5/6] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio() Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 6/6] cpufreq/amd-pstate: Get highest freq from CPPC if available Mario Limonciello (AMD)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
Rename amd_get_boost_ratio_numerator() to amd_get_effective_highest_perf()
to better reflect that it returns the effective highest performance value
for a CPU, accounting for preferred cores and heterogeneous topologies.
Add a new helper amd_get_boost_ratio() for doing both for boost
ratio calculations and update callers to use it.
This refactoring is needed because on some AMD systems (Zen6+),
the boost ratio should be calculated from frequency values rather than
performance values.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
arch/x86/kernel/acpi/cppc.c | 122 ++++++++++++++++++---------------
drivers/cpufreq/acpi-cpufreq.c | 5 +-
drivers/cpufreq/amd-pstate.c | 12 ++--
include/acpi/cppc_acpi.h | 9 ++-
4 files changed, 86 insertions(+), 62 deletions(-)
diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c
index be4c5e9e5ff6f..b581447711079 100644
--- a/arch/x86/kernel/acpi/cppc.c
+++ b/arch/x86/kernel/acpi/cppc.c
@@ -81,31 +81,18 @@ int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
static void amd_set_max_freq_ratio(void)
{
- struct cppc_perf_caps perf_caps;
- u64 numerator, nominal_perf;
+ u64 numerator, denominator;
u64 perf_ratio;
int rc;
- rc = cppc_get_perf_caps(0, &perf_caps);
- if (rc) {
- pr_debug("Could not retrieve perf counters (%d)\n", rc);
- return;
- }
-
- rc = amd_get_boost_ratio_numerator(0, &numerator);
+ rc = amd_get_boost_ratio(0, &numerator, &denominator);
if (rc) {
- pr_debug("Could not retrieve highest performance (%d)\n", rc);
- return;
- }
- nominal_perf = perf_caps.nominal_perf;
-
- if (!nominal_perf) {
- pr_debug("Could not retrieve nominal performance\n");
+ pr_debug("Could not retrieve boost ratio (%d)\n", rc);
return;
}
/* midpoint between max_boost and max_P */
- perf_ratio = (div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf) + SCHED_CAPACITY_SCALE) >> 1;
+ perf_ratio = (div_u64(numerator * SCHED_CAPACITY_SCALE, denominator) + SCHED_CAPACITY_SCALE) >> 1;
freq_invariance_set_perf_ratio(perf_ratio, false);
}
@@ -225,21 +212,18 @@ int amd_detect_prefcore(bool *detected)
EXPORT_SYMBOL_GPL(amd_detect_prefcore);
/**
- * amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
- * @cpu: CPU to get numerator for.
- * @numerator: Output variable for numerator.
+ * amd_get_effective_highest_perf: Get the effective highest performance value
+ * @cpu: CPU to get highest performance for.
*
- * Determine the numerator to use for calculating the boost ratio on
- * a CPU. On systems that support preferred cores, this will be a hardcoded
- * value. On other systems this will the highest performance register value.
+ * Get the effective highest performance value for a CPU, accounting for
+ * preferred cores and heterogeneous topologies. On systems with preferred
+ * cores, this may be a hardcoded value. On heterogeneous systems, this
+ * may be a per-CPU value. On other systems, this is the shared highest
+ * performance value.
*
- * If booting the system with amd-pstate enabled but preferred cores disabled then
- * the correct boost numerator will be returned to match hardware capabilities
- * even if the preferred cores scheduling hints are not enabled.
- *
- * Return: 0 for success, negative error code otherwise.
+ * Return: Effective highest performance value, or negative error code.
*/
-int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
+int amd_get_effective_highest_perf(unsigned int cpu)
{
enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu));
bool prefcore;
@@ -247,14 +231,12 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
u32 tmp;
ret = amd_detect_prefcore(&prefcore);
- if (ret)
+ if (ret < 0)
return ret;
/* without preferred cores, return the highest perf register value */
- if (!prefcore) {
- *numerator = boost_numerator;
- return 0;
- }
+ if (!prefcore)
+ return boost_numerator;
/*
* For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
@@ -264,8 +246,7 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
if (cpu_feature_enabled(X86_FEATURE_ZEN4)) {
switch (boot_cpu_data.x86_model) {
case 0x70 ... 0x7f:
- *numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
- return 0;
+ return CPPC_HIGHEST_PERF_PERFORMANCE;
default:
break;
}
@@ -273,26 +254,59 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
/* detect if running on heterogeneous design */
if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) {
- switch (core_type) {
- case TOPO_CPU_TYPE_UNKNOWN:
- pr_warn("Undefined core type found for cpu %d\n", cpu);
- break;
- case TOPO_CPU_TYPE_PERFORMANCE:
- /* use the max scale for performance cores */
- *numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
- return 0;
- case TOPO_CPU_TYPE_EFFICIENCY:
- /* use the highest perf value for efficiency cores */
- ret = amd_get_highest_perf(cpu, &tmp);
- if (ret)
- return ret;
- *numerator = tmp;
- return 0;
- }
+ if (cpu_feature_enabled(X86_FEATURE_ZEN5) &&
+ core_type == TOPO_CPU_TYPE_PERFORMANCE)
+ return CPPC_HIGHEST_PERF_PERFORMANCE;
+
+ /* Zen 5 efficiency, and Zen 6+ */
+ ret = amd_get_highest_perf(cpu, &tmp);
+ if (ret < 0)
+ return ret;
+
+ return tmp;
+ }
+
+ return CPPC_HIGHEST_PERF_PREFCORE;
+}
+EXPORT_SYMBOL_GPL(amd_get_effective_highest_perf);
+
+/**
+ * amd_get_boost_ratio: Get numerator and denominator for boost ratio
+ * @cpu: CPU to get the boost ratio for.
+ * @numerator: Output variable for numerator.
+ * @denominator: Output variable for denominator.
+ *
+ * Get the numerator and denominator for calculating the boost ratio.
+ *
+ * Return: 0 for success, negative error code otherwise.
+ */
+int amd_get_boost_ratio(unsigned int cpu, u64 *numerator, u64 *denominator)
+{
+ struct cppc_perf_caps perf_caps;
+ int ret;
+
+ ret = cppc_get_perf_caps(cpu, &perf_caps);
+ if (ret)
+ return ret;
+
+ /* Use frequency values if available */
+ if (perf_caps.highest_freq && perf_caps.nominal_freq) {
+ *numerator = perf_caps.highest_freq;
+ *denominator = perf_caps.nominal_freq;
+ return 0;
}
- *numerator = CPPC_HIGHEST_PERF_PREFCORE;
+ /* Fall back to performance values */
+ ret = amd_get_effective_highest_perf(cpu);
+ if (ret < 0)
+ return ret;
+
+ *numerator = ret;
+
+ *denominator = perf_caps.nominal_perf;
+ if (!*denominator)
+ return -EINVAL;
return 0;
}
-EXPORT_SYMBOL_GPL(amd_get_boost_ratio_numerator);
+EXPORT_SYMBOL_GPL(amd_get_boost_ratio);
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 21639d9ac753b..a1a005b29daba 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -640,12 +640,13 @@ static u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
}
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
- ret = amd_get_boost_ratio_numerator(cpu, &highest_perf);
- if (ret) {
+ ret = amd_get_effective_highest_perf(cpu);
+ if (ret < 0) {
pr_debug("CPU%d: Unable to get boost ratio numerator (%d)\n",
cpu, ret);
return 0;
}
+ highest_perf = ret;
} else {
highest_perf = perf_caps.highest_perf;
}
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 453084c67327f..f5c7cc05220c4 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -476,10 +476,12 @@ static int msr_init_perf(struct amd_cpudata *cpudata)
if (ret)
return ret;
- ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
- if (ret)
+ ret = amd_get_effective_highest_perf(cpudata->cpu);
+ if (ret < 0)
return ret;
+ numerator = ret;
+
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req);
if (ret)
return ret;
@@ -520,10 +522,12 @@ static int shmem_init_perf(struct amd_cpudata *cpudata)
if (ret)
return ret;
- ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
- if (ret)
+ ret = amd_get_effective_highest_perf(cpudata->cpu);
+ if (ret < 0)
return ret;
+ numerator = ret;
+
perf.highest_perf = numerator;
perf.max_limit_perf = numerator;
perf.min_limit_perf = cppc_perf.lowest_perf;
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
index 79f1eef957a45..c25755630f8be 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -193,7 +193,8 @@ extern int cppc_set_auto_sel(int cpu, bool enable);
extern int cppc_get_perf_limited(int cpu, u64 *perf_limited);
extern int cppc_set_perf_limited(int cpu, u64 bits_to_clear);
extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
-extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
+extern int amd_get_effective_highest_perf(unsigned int cpu);
+extern int amd_get_boost_ratio(unsigned int cpu, u64 *numerator, u64 *denominator);
extern int amd_detect_prefcore(bool *detected);
#else /* !CONFIG_ACPI_CPPC_LIB */
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
@@ -300,7 +301,11 @@ static inline int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
{
return -ENODEV;
}
-static inline int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
+static inline int amd_get_effective_highest_perf(unsigned int cpu)
+{
+ return -EOPNOTSUPP;
+}
+static inline int amd_get_boost_ratio(unsigned int cpu, u64 *numerator, u64 *denominator)
{
return -EOPNOTSUPP;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/6] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio()
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
` (3 preceding siblings ...)
2026-04-27 3:55 ` [PATCH 4/6] ACPI: CPPC: Refactor boost ratio handling Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
2026-04-27 3:55 ` [PATCH 6/6] cpufreq/amd-pstate: Get highest freq from CPPC if available Mario Limonciello (AMD)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
Update get_max_boost_ratio() to use the new amd_get_boost_ratio()
helper function instead of calling amd_get_effective_highest_perf()
directly.
This ensures the boost ratio is calculated correctly on systems where
frequency values should be used instead of performance values.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/cpufreq/acpi-cpufreq.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index a1a005b29daba..6e80540311f60 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -626,7 +626,7 @@ static int acpi_cpufreq_blacklist(struct cpuinfo_x86 *c)
static u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
{
struct cppc_perf_caps perf_caps;
- u64 highest_perf, nominal_perf;
+ u64 numerator, denominator;
int ret;
if (acpi_pstate_strict)
@@ -640,33 +640,31 @@ static u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
}
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
- ret = amd_get_effective_highest_perf(cpu);
- if (ret < 0) {
- pr_debug("CPU%d: Unable to get boost ratio numerator (%d)\n",
+ ret = amd_get_boost_ratio(cpu, &numerator, &denominator);
+ if (ret) {
+ pr_debug("CPU%d: Unable to get boost ratio (%d)\n",
cpu, ret);
return 0;
}
- highest_perf = ret;
} else {
- highest_perf = perf_caps.highest_perf;
+ numerator = perf_caps.highest_perf;
+ denominator = perf_caps.nominal_perf;
}
- nominal_perf = perf_caps.nominal_perf;
-
if (nominal_freq)
*nominal_freq = perf_caps.nominal_freq * 1000;
- if (!highest_perf || !nominal_perf) {
+ if (!numerator || !denominator) {
pr_debug("CPU%d: highest or nominal performance missing\n", cpu);
return 0;
}
- if (highest_perf < nominal_perf) {
+ if (numerator < denominator) {
pr_debug("CPU%d: nominal performance above highest\n", cpu);
return 0;
}
- return div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
+ return div_u64(numerator << SCHED_CAPACITY_SHIFT, denominator);
}
#else
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 6/6] cpufreq/amd-pstate: Get highest freq from CPPC if available
2026-04-27 3:55 [PATCH 0/6] Add CPPC HighestFreq support Mario Limonciello (AMD)
` (4 preceding siblings ...)
2026-04-27 3:55 ` [PATCH 5/6] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio() Mario Limonciello (AMD)
@ 2026-04-27 3:55 ` Mario Limonciello (AMD)
5 siblings, 0 replies; 7+ messages in thread
From: Mario Limonciello (AMD) @ 2026-04-27 3:55 UTC (permalink / raw)
To: Rafael J . Wysocki ⏎
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
If the _CPC object advertises the highest frequency for a CPU,
use this instead of trying to calculate by linear interpolation.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/cpufreq/amd-pstate.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index f5c7cc05220c4..9703b54ee4820 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1026,8 +1026,12 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
+ /* max freq came from _CPC */
+ if (cppc_perf.highest_freq)
+ max_freq = cppc_perf.highest_freq * 1000;
/* max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf */
- max_freq = perf_to_freq(perf, nominal_freq, perf.highest_perf);
+ else
+ max_freq = perf_to_freq(perf, nominal_freq, perf.highest_perf);
WRITE_ONCE(cpudata->max_freq, max_freq);
lowest_nonlinear_freq = perf_to_freq(perf, nominal_freq, perf.lowest_nonlinear_perf);
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread