This is a note to let you know that I've just added the patch titled hwmon: (emc2305) fix pwm never being able to set lower to the 6.1-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: hwmon-emc2305-fix-pwm-never-being-able-to-set-lower.patch and it can be found in the queue-6.1 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 28ecbb1ff7b48c690ce7cd5b9e6a46c96113f946 Author: Xingjiang Qiao <nanpuyue@xxxxxxxxx> Date: Tue Dec 6 13:53:31 2022 +0800 hwmon: (emc2305) fix pwm never being able to set lower [ Upstream commit 364ffd2537c44cb6914ff5669153f4a86fffad29 ] There are fields 'last_hwmon_state' and 'last_thermal_state' in the structure 'emc2305_cdev_data', which respectively store the cooling state set by the 'hwmon' and 'thermal' subsystem, and the driver author hopes that if the state set by 'hwmon' is lower than the value set by 'thermal', the driver will just save it without actually setting the pwm. Currently, the 'last_thermal_state' also be updated by 'hwmon', which will cause the cooling state to never be set to a lower value. This patch fixes that. Signed-off-by: Xingjiang Qiao <nanpuyue@xxxxxxxxx> Link: https://lore.kernel.org/r/20221206055331.170459-2-nanpuyue@xxxxxxxxx Fixes: 0d8400c5a2ce1 ("hwmon: (emc2305) add support for EMC2301/2/3/5 RPM-based PWM Fan Speed Controller.") [groeck: renamed emc2305_set_cur_state_shim -> __emc2305_set_cur_state] Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 9a78ca22541e..e42ae43f3de4 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -171,22 +171,12 @@ static int emc2305_get_max_state(struct thermal_cooling_device *cdev, unsigned l return 0; } -static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) +static int __emc2305_set_cur_state(struct emc2305_data *data, int cdev_idx, unsigned long state) { - int cdev_idx, ret; - struct emc2305_data *data = cdev->devdata; + int ret; struct i2c_client *client = data->client; u8 val, i; - if (state > data->max_state) - return -EINVAL; - - cdev_idx = emc2305_get_cdev_idx(cdev); - if (cdev_idx < 0) - return cdev_idx; - - /* Save thermal state. */ - data->cdev_data[cdev_idx].last_thermal_state = state; state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state); val = EMC2305_PWM_STATE2DUTY(state, data->max_state, EMC2305_FAN_MAX); @@ -211,6 +201,27 @@ static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned l return 0; } +static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) +{ + int cdev_idx, ret; + struct emc2305_data *data = cdev->devdata; + + if (state > data->max_state) + return -EINVAL; + + cdev_idx = emc2305_get_cdev_idx(cdev); + if (cdev_idx < 0) + return cdev_idx; + + /* Save thermal state. */ + data->cdev_data[cdev_idx].last_thermal_state = state; + ret = __emc2305_set_cur_state(data, cdev_idx, state); + if (ret < 0) + return ret; + + return 0; +} + static const struct thermal_cooling_device_ops emc2305_cooling_ops = { .get_max_state = emc2305_get_max_state, .get_cur_state = emc2305_get_cur_state, @@ -401,7 +412,7 @@ emc2305_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int ch */ if (data->cdev_data[cdev_idx].last_hwmon_state >= data->cdev_data[cdev_idx].last_thermal_state) - return emc2305_set_cur_state(data->cdev_data[cdev_idx].cdev, + return __emc2305_set_cur_state(data, cdev_idx, data->cdev_data[cdev_idx].last_hwmon_state); return 0; }