From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:18:11
Few rare race conditions were found when testing the Dynamic EPP feature
on EPYC platforms:
o Toggling dynamic EPP is essentially a driver switch into the same mode
and can race with an admin-initiated driver switch which can cause the
system to hang.
o If a profile change / power supply status change races with the driver
unloading, it can overwrite the Floor Perf restored in the CPPC_REQ
register that was meant to be left untouched until the next driver
load.
o When dynamic mode is disabled, the default EPP hint is set based on
the power supply mode at the time of driver load which can cause the
battery to drain faster when starting off from AC supply and then
switching to battery.
When fixing and testing the above, a couple of incorrect error codes
were noted which is also fixed in the series along with the unit test.
Series is based on mainline at v7.1-rc2 release tag. Thanks to Mario for
initial review. Feedback is greatly appreciated.
---
K Prateek Nayak (6):
cpufreq/amd-pstate: Grab "amd_pstate_driver_lock" when toggling
dynamic_epp
cpufreq/amd-pstate: Return -ENOMEM on failure to allocate profile_name
cpufreq/amd-pstate: Allow writes to dynamic_epp when state isn't
modified
cpufreq/amd-pstate: Reorder notifier unregistration and floor perf
reset
cpufreq/amd-pstate: Use "epp_default_dc" as default when dynamic_epp
is disabled
cpufreq/amd-pstate-ut: Drop policy reference before driver switch
drivers/cpufreq/amd-pstate-ut.c | 36 ++++++++++++++++++++++++++-------
drivers/cpufreq/amd-pstate.c | 23 ++++++++++++++++-----
2 files changed, 47 insertions(+), 12 deletions(-)
base-commit: 7fd2df204f342fc17d1a0bfcd474b24232fb0f32
--
2.34.1
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:18:28
Concurrently changing driver mode and dynamic_epp with:
echo passive > /sys/devices/system/cpu/amd_pstate/status&
echo disable > /sys/devices/system/cpu/amd_pstate/dynamic_epp&
hits the WARN_ON_ONCE() in static_key_disable_cpuslocked() and hangs the
system since both sysfs writes are trying to do
amd_pstate_change_driver_mode() without any synchronization.
Grab the "amd_pstate_driver_lock" mutex when modifying "dynamic_epp" to
prevent the two paths from racing with each other. Add a lockdep
assertion for "amd_pstate_driver_lock" in
amd_pstate_change_driver_mode() to formalize the dependency.
Since "cppc_mode" is stable under "amd_pstate_driver_lock", only reload
the driver when in "AMD_PSTATE_ACTIVE" mode and reject all writes when
in passive or guided mode, or if the driver is not loaded, since only
active mode operates on EPP.
Fixes: e30ca6dd5345 ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate.c | 9 +++++++++
1 file changed, 9 insertions(+)
@@ -1707,6 +1707,8 @@ static int amd_pstate_change_driver_mode(int mode){intret;+lockdep_assert_held(&amd_pstate_driver_lock);+ret=amd_pstate_unregister_driver(0);if(ret)returnret;
@@ -1821,6 +1823,13 @@ static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,if(ret)returnret;+guard(mutex)(&amd_pstate_driver_lock);++if(cppc_state!=AMD_PSTATE_ACTIVE){+pr_debug("dynamic_epp can only be toggled in active mode\n");+return-EINVAL;+}+if(dynamic_epp==enabled)return-EINVAL;
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:18:45
Failure to allocate profile name will return -EINVAL from
platform_profile_register() while in fact, it is a failure to allocate
memory for the profile_name string.
Return -ENOMEM when kasprintf() fails to allocate profile_name string.
Fixes: e30ca6dd5345 ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate.c | 2 ++
1 file changed, 2 insertions(+)
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:18:59
Writing the current "dynamic_epp" state to sysfs fails with -EINVAL even
though the desired result was achieved. Allow writes to "dynamic_epp"
that does not modify the state.
Fixes: e30ca6dd5345 ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:19:16
An active power supply notifier can race with amd_pstate_epp_cpu_exit()
trying to reset the floor perf and can overwrite the floor perf set in
MSR_AMD_CPPC_REQ.
Unregister the notifier before setting the floor perf to prevent the
rare race.
Fixes: e30ca6dd5345 ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:19:31
If "dynamic_epp" is disabled, the driver initialization and the default
EPP selection from sysfs currently sets the EPP based on the power
supply state of the system at that time but there is no power supply
callbacks registered to toggle it when the power supply state changes.
This can lead to faster battery drain on platforms that start off while
being plugged to the wall but later move to battery power since the EPP
stays at AMD_CPPC_EPP_PERFORMANCE.
Use "epp_default_dc" as the default EPP selection when dynamic_epp is
disabled, restoring older behavior. On servers, this defaults to
AMD_CPPC_EPP_PERFORMANCE and on other platforms, it defaults to
AMD_CPPC_EPP_BALANCE_PERFORMANCE.
Fixes: e30ca6dd5345 ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: K Prateek Nayak <kprateek.nayak@amd.com> Date: 2026-05-08 05:19:48
Recent changes to the EPP unit test tries to perform a driver switch
with a cpufreq_policy reference held when the driver is loaded into
anything but the active mode which leads to a circular dependency and
the unit test hanging indefinitely.
Drop the reference before driver switch and grab it back once the driver
mode is stabilized for the test.
The EPP writes are only possible with CPUFREQ_POLICY_POWERSAVE policy.
Temporarily switch the cpudata->policy (while holding the write end of
the policy->rwsem) to CPUFREQ_POLICY_POWERSAVE and restore the original
policy once tests are done. To ensure the final EPP is correct in case
the driver started with CPUFREQ_POLICY_PERFORMANCE, EPP performance is
tested last.
The __free() based cleanup for cpufreq_policy is lost in the process.
Reported-by: Kalpana Shetty <redacted>
Fixes: 7e173bc310d2b ("cpufreq/amd-pstate-ut: Add a unit test for raw EPP")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
drivers/cpufreq/amd-pstate-ut.c | 36 ++++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 7 deletions(-)
@@ -274,20 +274,21 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)staticintamd_pstate_ut_epp(u32index){-structcpufreq_policy*policy__free(put_cpufreq_policy)=NULL;-char*buf__free(cleanup_page)=NULL;staticconstchar*constepp_strings[]={-"performance",-"balance_performance",-"balance_power","power",+"balance_power",+"balance_performance",+"performance",};-structamd_cpudata*cpudata;+char*buf__free(cleanup_page)=NULL;+structcpufreq_policy*policy=NULL;enumamd_pstate_modeorig_mode;+structamd_cpudata*cpudata;+unsignedlongorig_policy;boolorig_dynamic_epp;intret,cpu=0;-inti;u16epp;+inti;policy=cpufreq_cpu_get(cpu);if(!policy)
@@ -297,6 +298,10 @@ static int amd_pstate_ut_epp(u32 index)orig_mode=amd_pstate_get_status();orig_dynamic_epp=cpudata->dynamic_epp;+/* Drop reference before potential driver change. */+cpufreq_cpu_put(policy);+policy=NULL;+/* disable dynamic EPP before running test */if(cpudata->dynamic_epp){pr_debug("Dynamic EPP is enabled, disabling it\n");
@@ -311,6 +316,17 @@ static int amd_pstate_ut_epp(u32 index)if(ret)gotoout;+policy=cpufreq_cpu_get(cpu);+if(!policy){+ret=-ENODEV;+gotoout;+}++down_write(&policy->rwsem);+cpudata=policy->driver_data;+orig_policy=cpudata->policy;+cpudata->policy=CPUFREQ_POLICY_POWERSAVE;+for(epp=0;epp<=U8_MAX;epp++){u8val;
@@ -358,6 +374,12 @@ static int amd_pstate_ut_epp(u32 index)ret=0;out:+if(policy){+cpudata->policy=orig_policy;+up_write(&policy->rwsem);+cpufreq_cpu_put(policy);+}+if(orig_dynamic_epp){intret2;
From: Mario Limonciello <mario.limonciello@amd.com> Date: 2026-05-08 18:04:34
On 5/8/26 00:17, K Prateek Nayak wrote:
Few rare race conditions were found when testing the Dynamic EPP feature
on EPYC platforms:
o Toggling dynamic EPP is essentially a driver switch into the same mode
and can race with an admin-initiated driver switch which can cause the
system to hang.
o If a profile change / power supply status change races with the driver
unloading, it can overwrite the Floor Perf restored in the CPPC_REQ
register that was meant to be left untouched until the next driver
load.
o When dynamic mode is disabled, the default EPP hint is set based on
the power supply mode at the time of driver load which can cause the
battery to drain faster when starting off from AC supply and then
switching to battery.
When fixing and testing the above, a couple of incorrect error codes
were noted which is also fixed in the series along with the unit test.
Series is based on mainline at v7.1-rc2 release tag. Thanks to Mario for
initial review. Feedback is greatly appreciated.
---
K Prateek Nayak (6):
cpufreq/amd-pstate: Grab "amd_pstate_driver_lock" when toggling
dynamic_epp
cpufreq/amd-pstate: Return -ENOMEM on failure to allocate profile_name
cpufreq/amd-pstate: Allow writes to dynamic_epp when state isn't
modified
cpufreq/amd-pstate: Reorder notifier unregistration and floor perf
reset
cpufreq/amd-pstate: Use "epp_default_dc" as default when dynamic_epp
is disabled
cpufreq/amd-pstate-ut: Drop policy reference before driver switch
drivers/cpufreq/amd-pstate-ut.c | 36 ++++++++++++++++++++++++++-------
drivers/cpufreq/amd-pstate.c | 23 ++++++++++++++++-----
2 files changed, 47 insertions(+), 12 deletions(-)
base-commit: 7fd2df204f342fc17d1a0bfcd474b24232fb0f32
Much appreciated. I've staged these in amd-pstate-fixes and will send out the PR next week after more testing.