Okay, no problem, I'll get rid of the full-speed mode (and update the documentation) in the next version of the patch. Do you think I should disable the value "0" in pwm*_enable? Václav út 20. 4. 2021 v 0:33 odesílatel Guenter Roeck <linux@xxxxxxxxxxxx> napsal: > > On Tue, Apr 13, 2021 at 04:59:45AM +0200, Václav Kubernát wrote: > > In the old code, pwm*_enable does two things. Firstly, it sets whether > > the chip should run in PWM or RPM mode. Secondly, it tells the chip > > whether it should monitor fan RPM. However, these two settings aren't > > tied together, so they shouldn't be set with a single value. In the new > > code, fan*_enable now controls fan RPM monitoring (pwm*_enable no longer > > controls that). > > > > According to the sysfs hwmon documentation, pwm*_enable has three > > possible values, 0 for "no control / full-speed", 1 for manual mode, and > > 2+ for automatic. The old code works fine for 1 and 2, but 0 only > > differs from 1 in that it just turns off fan speed monitoring. The chip > > actually does have a way to turn off fan controls (and only monitor), > > but what that does is that it sets PWM to 0% duty cycle (which is the > > opposite to full-speed) AND it also turns off fan speed monitoring. > > Because of this, I implemented the 0 value by setting PWM mode to 100%. > > This method does come with a problem: it is impossible to differentiate > > between full-speed and PWM mode just from the values on the chip. The > > new code solves this by saving a value indicating whether we're in > > full-speed mode. This value is initialized to 0, so full-speed mode > > won't persist across reboots. > > > I don't think this is a good idea, sorry. It is not just a problem across > reboots, but also when unloading and reloading the driver. I think we > should stick with chip capabilities and adjust the documentation > accordingly. > > Guenter > > > These two changes are closely connected together, mainly because the > > detection of the pwm*_enable value depended on whether fan speed > > monitoring is enabled (which is now controlled as written in the first > > paragraph). > > > > Signed-off-by: Václav Kubernát <kubernat@xxxxxxxxx> > > --- > > Documentation/hwmon/max31790.rst | 8 +-- > > drivers/hwmon/max31790.c | 87 ++++++++++++++++++++++---------- > > 2 files changed, 66 insertions(+), 29 deletions(-) > > > > diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst > > index f301385d8cef..8979c8a02cd1 100644 > > --- a/Documentation/hwmon/max31790.rst > > +++ b/Documentation/hwmon/max31790.rst > > @@ -34,10 +34,12 @@ also be configured to serve as tachometer inputs. > > Sysfs entries > > ------------- > > > > -================== === ======================================================= > > +================== === ============================================================= > > +fan[1-12]_enable RW enable fan speed monitoring > > fan[1-12]_input RO fan tachometer speed in RPM > > fan[1-12]_fault RO fan experienced fault > > fan[1-6]_target RW desired fan speed in RPM > > -pwm[1-6]_enable RW regulator mode, 0=disabled, 1=manual mode, 2=rpm mode > > +pwm[1-6]_enable RW regulator mode, 0=full speed, 1=manual (pwm) mode, 2=rpm mode > > + setting rpm mode sets fan*_enable to 1 > > pwm[1-6] RW fan target duty cycle (0-255) > > -================== === ======================================================= > > +================== === ============================================================= > > diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c > > index e3765ce4444a..ecdd55e12ffe 100644 > > --- a/drivers/hwmon/max31790.c > > +++ b/drivers/hwmon/max31790.c > > @@ -39,6 +39,7 @@ > > > > #define FAN_RPM_MIN 120 > > #define FAN_RPM_MAX 7864320 > > +#define MAX_PWM 0XFF80 > > > > #define RPM_FROM_REG(reg, sr) (((reg) >> 4) ? \ > > ((60 * (sr) * 8192) / ((reg) >> 4)) : \ > > @@ -90,6 +91,7 @@ struct max31790_data { > > struct regmap *regmap; > > > > struct mutex update_lock; > > + bool full_speed[NR_CHANNEL]; > > u8 fan_config[NR_CHANNEL]; > > u8 fan_dynamics[NR_CHANNEL]; > > }; > > @@ -191,6 +193,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, > > else > > *val = !!(fault & (1 << channel)); > > return 0; > > + case hwmon_fan_enable: > > + *val = !!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN); > > + return 0; > > default: > > return -EOPNOTSUPP; > > } > > @@ -233,6 +238,15 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, > > MAX31790_REG_TARGET_COUNT(channel), > > target_count); > > break; > > + case hwmon_fan_enable: > > + if (val == 0) > > + data->fan_config[channel] &= ~MAX31790_FAN_CFG_TACH_INPUT_EN; > > + else > > + data->fan_config[channel] |= MAX31790_FAN_CFG_TACH_INPUT_EN; > > + err = regmap_write(regmap, > > + MAX31790_REG_FAN_CONFIG(channel), > > + data->fan_config[channel]); > > + break; > > default: > > err = -EOPNOTSUPP; > > break; > > @@ -260,6 +274,11 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) > > !(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) > > return 0644; > > return 0; > > + case hwmon_fan_enable: > > + if (channel < NR_CHANNEL || > > + (fan_config & MAX31790_FAN_CFG_TACH_INPUT)) > > + return 0644; > > + return 0; > > default: > > return 0; > > } > > @@ -281,12 +300,12 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel, > > *val = read >> 8; > > return 0; > > case hwmon_pwm_enable: > > - if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) > > + if (data->full_speed[channel]) > > + *val = 0; > > + else if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) > > *val = 2; > > - else if (data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN) > > + else > > *val = 1; > > - else > > - *val = 0; > > return 0; > > default: > > return -EOPNOTSUPP; > > @@ -305,28 +324,42 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, > > > > switch (attr) { > > case hwmon_pwm_input: > > - if (val < 0 || val > 255) { > > + if (data->full_speed[channel] || val < 0 || val > 255) { > > err = -EINVAL; > > break; > > } > > + > > err = write_reg_word(regmap, MAX31790_REG_PWMOUT(channel), val << 8); > > break; > > case hwmon_pwm_enable: > > fan_config = data->fan_config[channel]; > > - if (val == 0) { > > - fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN | > > - MAX31790_FAN_CFG_RPM_MODE); > > - } else if (val == 1) { > > - fan_config = (fan_config | > > - MAX31790_FAN_CFG_TACH_INPUT_EN) & > > - ~MAX31790_FAN_CFG_RPM_MODE; > > + if (val == 0 || val == 1) { > > + fan_config &= ~MAX31790_FAN_CFG_RPM_MODE; > > } else if (val == 2) { > > - fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN | > > - MAX31790_FAN_CFG_RPM_MODE; > > + fan_config |= MAX31790_FAN_CFG_RPM_MODE; > > } else { > > err = -EINVAL; > > break; > > } > > + > > + /* > > + * The chip sets PWM to zero when using its "monitor only" mode > > + * and 0 means full speed. > > + */ > > + if (val == 0) { > > + data->full_speed[channel] = true; > > + err = write_reg_word(regmap, MAX31790_REG_PWMOUT(channel), MAX_PWM); > > + } else { > > + data->full_speed[channel] = false; > > + } > > + > > + /* > > + * RPM mode implies enabled TACH input, so enable it in RPM > > + * mode. > > + */ > > + if (val == 2) > > + fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN; > > + > > data->fan_config[channel] = fan_config; > > err = regmap_write(regmap, > > MAX31790_REG_FAN_CONFIG(channel), > > @@ -400,18 +433,18 @@ static umode_t max31790_is_visible(const void *data, > > > > static const struct hwmon_channel_info *max31790_info[] = { > > HWMON_CHANNEL_INFO(fan, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT, > > - HWMON_F_INPUT | HWMON_F_FAULT), > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, > > + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT), > > HWMON_CHANNEL_INFO(pwm, > > HWMON_PWM_INPUT | HWMON_PWM_ENABLE, > > HWMON_PWM_INPUT | HWMON_PWM_ENABLE, > > @@ -448,6 +481,8 @@ static int max31790_init_client(struct regmap *regmap, > > if (rv < 0) > > return rv; > > data->fan_dynamics[i] = rv; > > + > > + data->full_speed[i] = false; > > } > > > > return 0;