Commit 9228169d authored by K Prateek Nayak's avatar K Prateek Nayak Committed by Mario Limonciello (AMD)
Browse files

cpufreq/amd-pstate: Grab "amd_pstate_driver_lock" when toggling dynamic_epp



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: e30ca6dd ("cpufreq/amd-pstate: Add dynamic energy performance preference")
Reviewed-by: default avatarMario Limonciello <mario.limonciello@amd.com>
Signed-off-by: default avatarK Prateek Nayak <kprateek.nayak@amd.com>
Link: https://lore.kernel.org/r/20260508051748.10484-2-kprateek.nayak@amd.com


Signed-off-by: default avatarMario Limonciello (AMD) <superm1@kernel.org>
parent 7fd2df20
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1707,6 +1707,8 @@ static int amd_pstate_change_driver_mode(int mode)
{
	int ret;

	lockdep_assert_held(&amd_pstate_driver_lock);

	ret = amd_pstate_unregister_driver(0);
	if (ret)
		return ret;
@@ -1821,6 +1823,13 @@ static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,
	if (ret)
		return ret;

	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;