* [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