* [PATCH v3 0/4] Add CPPC HighestFreq support
@ 2026-05-14 21:56 Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 1/4] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Mario Limonciello @ 2026-05-14 21:56 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-acpi, linux-kernel, linux-pm, K Prateek Nayak, x86,
Mario Limonciello
On some systems, the boost ratio cannot be accurately calculated
using linear interpolation of CPPC performance values because the
performance-to-frequency mapping is not linear across all cores.
This series introduces support for the CPPC HighestFreq register. This
register is under a proposal with ASWG at the moment and trending for
inclusion in ACPI 6.7.
This optionally provides the actual highest frequency eliminating
the need for interpolation. When available, this frequency value is used
for more accurate CPU capacity calculations and boost ratio determination.
This series adds support for the ACPI 6.7 proposal. It require's Sumit's
CPPC v4 patches.
---
v3:
* Rebase on Sumit's CPPCv4 v3 submission [1]
* Drop "Revert "ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn"
as this was merged through the PM tree already in 7.1-rc3.
* Add tags for Prateek.
v2:
* Drop CPPC v4 patches, these are submitted separately by Sumit Gupta [2]
Link: https://lore.kernel.org/linux-pm/20260514194822.1841748-1-sumitg@nvidia.com/ [1]
Link: https://lore.kernel.org/linux-pm/20260430142430.755437-1-sumitg@nvidia.com/ [2]
Mario Limonciello (4):
ACPI: CPPC: Add support for reading HighestFreq
ACPI: CPPC: Refactor boost ratio handling
cpufreq/acpi-cpufreq: Use amd_get_boost_ratio()
cpufreq/amd-pstate: Get highest freq from CPPC if available
arch/x86/kernel/acpi/cppc.c | 122 ++++++++++++++++++---------------
drivers/acpi/cppc_acpi.c | 31 ++++++---
drivers/cpufreq/acpi-cpufreq.c | 17 +++--
drivers/cpufreq/amd-pstate.c | 18 +++--
include/acpi/cppc_acpi.h | 16 ++++-
5 files changed, 123 insertions(+), 81 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/4] ACPI: CPPC: Add support for reading HighestFreq
2026-05-14 21:56 [PATCH v3 0/4] Add CPPC HighestFreq support Mario Limonciello
@ 2026-05-14 21:56 ` Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 2/4] ACPI: CPPC: Refactor boost ratio handling Mario Limonciello
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Mario Limonciello @ 2026-05-14 21:56 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.
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
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 ad6ece16c30df..befe3e3136a6a 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -134,7 +134,7 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
* cpc_regs[] with the corresponding index. 0 means mandatory and 1
* means optional.
*/
-#define REG_OPTIONAL (0x7FC7D0)
+#define REG_OPTIONAL (0x1FFC7D0)
/*
* Use the index of the register in per-cpu cpc_regs[] to check if
@@ -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);
@@ -756,14 +758,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_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;
@@ -1364,9 +1367,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;
@@ -1383,6 +1387,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 ?*/
@@ -1390,7 +1395,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;
@@ -1453,7 +1458,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)
@@ -1466,9 +1471,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 0b1dcdbea10a2..eb1eb40c6cb8d 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
@@ -113,6 +115,8 @@ enum cppc_regs {
NOMINAL_FREQ,
OSPM_NOMINAL_PERF,
RESOURCE_PRIORITY,
+ HIGHEST_FREQ,
+ CURRENT_FREQ,
};
/*
@@ -130,6 +134,7 @@ struct cppc_perf_caps {
u32 lowest_nonlinear_perf;
u32 lowest_freq;
u32 nominal_freq;
+ u32 highest_freq;
};
struct cppc_perf_ctrls {
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 2/4] ACPI: CPPC: Refactor boost ratio handling
2026-05-14 21:56 [PATCH v3 0/4] Add CPPC HighestFreq support Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 1/4] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello
@ 2026-05-14 21:56 ` Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 3/4] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio() Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 4/4] cpufreq/amd-pstate: Get highest freq from CPPC if available Mario Limonciello
3 siblings, 0 replies; 5+ messages in thread
From: Mario Limonciello @ 2026-05-14 21:56 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.
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
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 62b5d995281d2..ae8d67fb374bd 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -472,10 +472,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;
@@ -516,10 +518,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 eb1eb40c6cb8d..492ebacfe05b4 100644
--- a/include/acpi/cppc_acpi.h
+++ b/include/acpi/cppc_acpi.h
@@ -195,7 +195,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)
@@ -306,7 +307,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.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 3/4] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio()
2026-05-14 21:56 [PATCH v3 0/4] Add CPPC HighestFreq support Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 1/4] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 2/4] ACPI: CPPC: Refactor boost ratio handling Mario Limonciello
@ 2026-05-14 21:56 ` Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 4/4] cpufreq/amd-pstate: Get highest freq from CPPC if available Mario Limonciello
3 siblings, 0 replies; 5+ messages in thread
From: Mario Limonciello @ 2026-05-14 21:56 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.
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
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.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 4/4] cpufreq/amd-pstate: Get highest freq from CPPC if available
2026-05-14 21:56 [PATCH v3 0/4] Add CPPC HighestFreq support Mario Limonciello
` (2 preceding siblings ...)
2026-05-14 21:56 ` [PATCH v3 3/4] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio() Mario Limonciello
@ 2026-05-14 21:56 ` Mario Limonciello
3 siblings, 0 replies; 5+ messages in thread
From: Mario Limonciello @ 2026-05-14 21:56 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.
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
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 ae8d67fb374bd..3f06e33f47120 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1022,8 +1022,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.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-14 21:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 21:56 [PATCH v3 0/4] Add CPPC HighestFreq support Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 1/4] ACPI: CPPC: Add support for reading HighestFreq Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 2/4] ACPI: CPPC: Refactor boost ratio handling Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 3/4] cpufreq/acpi-cpufreq: Use amd_get_boost_ratio() Mario Limonciello
2026-05-14 21:56 ` [PATCH v3 4/4] cpufreq/amd-pstate: Get highest freq from CPPC if available Mario Limonciello
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox