[PATCH v2 2/2] cpufreq/amd-pstate: Prevent active mode on systems without EPP support
From: Marco Scardovi
Date: Wed Jun 03 2026 - 08:14:08 EST
Some AMD processors or firmware configurations do not support Collaborative
Processor Performance Control (CPPC) Energy Performance Preference (EPP).
When loading the amd-pstate driver in EPP-reliant "active" mode on these
systems, the driver fails to function correctly.
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. EPP capability is uniform across all CPUs on x86,
making a single CPU query sufficient.
Treat EPP support as a tri-state during probing:
- Success: EPP is supported.
- -EOPNOTSUPP: EPP is definitively unsupported.
- Unknown error: Warn about the unexpected failure, but default to assuming
EPP is supported to avoid false negatives.
Cache the capability in a static global `epp_supported` boolean to avoid
redundant capability checks during runtime mode switches.
If EPP is unsupported:
- Fall back to passive mode at boot to keep the driver functional rather
than failing to load entirely.
- Reject runtime switches to active mode via sysfs with -ENODEV and print
a warning.
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 | 44 ++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index e8057f3dfb1e..cd052880ecb3 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;
/*
@@ -1772,6 +1775,11 @@ int amd_pstate_update_status(const char *buf, size_t size)
if (mode_idx < 0)
return mode_idx;
+ if (mode_idx == AMD_PSTATE_ACTIVE && !epp_supported) {
+ pr_warn("EPP is not supported by this processor, active mode rejected\n");
+ return -ENODEV;
+ }
+
if (mode_state_machine[cppc_state][mode_idx]) {
guard(mutex)(&amd_pstate_driver_lock);
return mode_state_machine[cppc_state][mode_idx](mode_idx);
@@ -2229,6 +2237,36 @@ 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;
+
+ /*
+ * On symmetric x86 systems, CPPC EPP support is uniform across all
+ * CPUs. Probing the first online CPU is sufficient to determine
+ * system-wide capability.
+ */
+ ret = cppc_get_epp_perf(cpu, &epp);
+ if (!ret)
+ return true;
+
+ /*
+ * We treat EPP support as a tri-state:
+ * - Success (0): EPP is supported.
+ * - Unsupported (-EOPNOTSUPP): EPP is definitively unsupported.
+ * - Unknown error (others): Warn about the unexpected failure, but
+ * default to assuming support to avoid false negatives (this may
+ * be revisited if transient errors cause driver instability).
+ */
+ if (ret == -EOPNOTSUPP)
+ return false;
+
+ pr_warn("Unable to determine EPP capability: %d\n", ret);
+ return true;
+}
+
static int __init amd_pstate_init(void)
{
struct device *dev_root;
@@ -2251,6 +2289,12 @@ static int __init amd_pstate_init(void)
if (cpufreq_get_current_driver())
return -EEXIST;
+ 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;
+ }
+
quirks = NULL;
/* check if this machine need CPPC quirks */
--
2.54.0