[PATCH 1/1] cpufreq/amd-pstate: Prevent active mode on systems without EPP support

From: Marco Scardovi

Date: Wed Jun 03 2026 - 04:26:05 EST


Zen 2 and older AMD processors do not support Collaborative Processor
Performance Control (CPPC) Energy Performance Preference (EPP). Loading
the amd-pstate driver in EPP-reliant "active" mode on these systems
pins the CPU frequency to the lowest non-linear frequency (1.7GHz).

Unconditionally probe EPP support during driver initialization via a new
amd_pstate_epp_supported() helper, which queries cppc_get_epp_perf() on
the first online CPU. Lack of ENERGY_PERF support or any error from
cppc_get_epp_perf() causes EPP to be treated as unsupported, with
unexpected errors printing a warning.

Cache the capability in a static global `epp_supported` boolean to avoid
redundant register reads during runtime mode transitions.

If EPP is unsupported:
- Fall back to passive mode at boot to keep the system functional.
- Reject runtime switches to active mode with -ENODEV.

Fixes: ffa5096a7c33 ("cpufreq: amd-pstate: implement Pstate EPP support for the AMD processors")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221473
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs@xxxxxxxxxxx>
---
drivers/cpufreq/amd-pstate.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 8d55e2be825b..61b75e3999b5 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <linux/cpumask.h>
#include <linux/sched.h>
#include <linux/cpufreq.h>
#include <linux/compiler.h>
@@ -88,6 +89,8 @@ static struct cpufreq_driver amd_pstate_epp_driver;
static int cppc_state = AMD_PSTATE_UNDEFINED;
static bool amd_pstate_prefcore = true;
static bool dynamic_epp;
+/* EPP support capability cached for driver mode switches. */
+static bool epp_supported;
static struct quirk_entry *quirks;

/*
@@ -1614,6 +1617,10 @@ static void amd_pstate_driver_cleanup(void)
static int amd_pstate_set_driver(int mode_idx)
{
if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
+ if (mode_idx == AMD_PSTATE_ACTIVE && !epp_supported) {
+ pr_debug("EPP is not supported by this processor\n");
+ return -ENODEV;
+ }
cppc_state = mode_idx;
if (cppc_state == AMD_PSTATE_DISABLE)
pr_info("driver is explicitly disabled\n");
@@ -2222,6 +2229,22 @@ static bool amd_cppc_supported(void)
return true;
}

+static bool amd_pstate_epp_supported(void)
+{
+ unsigned int cpu = cpumask_first(cpu_online_mask);
+ u64 epp;
+ int ret;
+
+ ret = cppc_get_epp_perf(cpu, &epp);
+ if (!ret)
+ return true;
+
+ if (ret != -EOPNOTSUPP)
+ pr_warn("Unable to determine EPP capability: %d\n", ret);
+
+ return false;
+}
+
static int __init amd_pstate_init(void)
{
struct device *dev_root;
@@ -2274,6 +2297,12 @@ static int __init amd_pstate_init(void)
return -ENODEV;
}

+ epp_supported = amd_pstate_epp_supported();
+ if (cppc_state == AMD_PSTATE_ACTIVE && !epp_supported) {
+ pr_warn("EPP not supported, falling back to passive mode\n");
+ cppc_state = AMD_PSTATE_PASSIVE;
+ }
+
/* capability check */
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
pr_debug("AMD CPPC MSR based functionality is supported\n");
--
2.54.0