Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (mlxreg-fan) Separate methods of fan setting coming from different subsystems

Distinct between fan speed setting request coming for hwmon and
thermal subsystems.

There are fields 'last_hwmon_state' and 'last_thermal_state' in the
structure 'mlxreg_fan_pwm', which respectively store the cooling state
set by the 'hwmon' and 'thermal' subsystem.
The purpose is to make arbitration of fan speed setting. For example, if
fan speed required to be not lower than some limit, such setting is to
be performed through 'hwmon' subsystem, thus 'thermal' subsystem will
not set fan below this limit.

Currently, the 'last_thermal_state' is also be updated by 'hwmon' causing
cooling state to never be set to a lower value.

Eliminate update of 'last_thermal_state', when request is coming from
'hwmon' subsystem.

Fixes: da74944d3a46 ("hwmon: (mlxreg-fan) Use pwm attribute for setting fan speed low limit")
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Link: https://lore.kernel.org/r/20250113084859.27064-2-vadimp@nvidia.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Vadim Pasternak and committed by
Guenter Roeck
c02e4644 5798b628

+16 -8
+16 -8
drivers/hwmon/mlxreg-fan.c
··· 113 113 int divider; 114 114 }; 115 115 116 - static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, 117 - unsigned long state); 116 + static int _mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, 117 + unsigned long state, bool thermal); 118 118 119 119 static int 120 120 mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, ··· 224 224 * last thermal state. 225 225 */ 226 226 if (pwm->last_hwmon_state >= pwm->last_thermal_state) 227 - return mlxreg_fan_set_cur_state(pwm->cdev, 228 - pwm->last_hwmon_state); 227 + return _mlxreg_fan_set_cur_state(pwm->cdev, 228 + pwm->last_hwmon_state, 229 + false); 229 230 return 0; 230 231 } 231 232 return regmap_write(fan->regmap, pwm->reg, val); ··· 358 357 return 0; 359 358 } 360 359 361 - static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, 362 - unsigned long state) 363 - 360 + static int _mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, 361 + unsigned long state, bool thermal) 364 362 { 365 363 struct mlxreg_fan_pwm *pwm = cdev->devdata; 366 364 struct mlxreg_fan *fan = pwm->fan; ··· 369 369 return -EINVAL; 370 370 371 371 /* Save thermal state. */ 372 - pwm->last_thermal_state = state; 372 + if (thermal) 373 + pwm->last_thermal_state = state; 373 374 374 375 state = max_t(unsigned long, state, pwm->last_hwmon_state); 375 376 err = regmap_write(fan->regmap, pwm->reg, ··· 380 379 return err; 381 380 } 382 381 return 0; 382 + } 383 + 384 + static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, 385 + unsigned long state) 386 + 387 + { 388 + return _mlxreg_fan_set_cur_state(cdev, state, true); 383 389 } 384 390 385 391 static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = {