From f324179e6ccd05dfdc8e98fba2e9d50aea8e7ea2 Mon Sep 17 00:00:00 2001 From: "Baek Kyu, Kim" Date: Sat, 31 Oct 2026 18:50:39 +0900 Subject: [PATCH] hwmon: (gpio-fan) Update the speed cache before dropping the PM reference set_fan_speed() writes the GPIO control value before dropping the runtime PM reference when stopping the fan. pm_runtime_put_sync() decrements the usage count even when suspending the device fails, but the error return currently leaves speed_index at the previous running speed. A request for that same running speed then returns success without changing the GPIOs or taking a runtime PM reference. Retrying the stop instead drops a reference the driver no longer owns and can trigger a runtime PM usage count underflow warning. Update speed_index after writing the GPIOs and before dropping the PM reference. The initial same-speed check already excludes a stopped fan, so a zero target is sufficient to identify the transition that needs a PM put. Preserve the PM error return and the CONFIG_PM=n exception. This keeps the cached control state and PM reference ownership consistent without restoring running GPIOs after a possibly partial supply failure. It does not clear persistent runtime PM errors or claim that a failing regulator has successfully powered off. Fixes: 0d01110e6356 ("hwmon: (gpio-fan) Add regulator support") Cc: stable@vger.kernel.org Signed-off-by: Baek Kyu, Kim Link: https://patch.msgid.link/20261031095039.11683-1-pocj8ur4in@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/gpio-fan.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 3f78375eeb44..08b58b49be5b 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -150,7 +150,10 @@ static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index) __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val); - if (fan_data->speed_index > 0 && speed_index == 0) { + /* The GPIOs have changed, and a PM put drops the reference on error. */ + fan_data->speed_index = speed_index; + + if (speed_index == 0) { int ret; ret = pm_runtime_put_sync(fan_data->dev); @@ -158,8 +161,6 @@ static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index) return ret; } - fan_data->speed_index = speed_index; - return 0; }