Skip to content

Commit

Permalink
hwmon: (nct7802) Fix overflows seen when writing into limit attributes
Browse files Browse the repository at this point in the history
Fix overflows seen when writing voltage and temperature limit attributes.

The value passed to DIV_ROUND_CLOSEST() needs to be clamped, and the
value parameter passed to nct7802_write_fan_min() is an unsigned long.

Also, writing values larger than 2700000 into a fan limit attribute results
in writing 0 into the chip's limit registers. The exact behavior when
writing this value is unspecified. For consistency, report a limit of
1350000 if the chip register reads 0. This may be wrong, and the chip
behavior should be verified with the actual chip, but it is better than
reporting a value of 0 (which, when written, results in writing a value
of 0x1fff into the chip register).

Fixes: 3434f37 ("hwmon: Driver for Nuvoton NCT7802Y")
Reviewed-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Guenter Roeck committed Dec 12, 2016
1 parent 64bd708 commit c0d04e9
Showing 1 changed file with 5 additions and 3 deletions.
8 changes: 5 additions & 3 deletions drivers/hwmon/nct7802.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,15 @@ static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
ret = 0;
else if (ret)
ret = DIV_ROUND_CLOSEST(1350000U, ret);
else
ret = 1350000U;
abort:
mutex_unlock(&data->access_lock);
return ret;
}

static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low,
u8 reg_fan_high, unsigned int limit)
u8 reg_fan_high, unsigned long limit)
{
int err;

Expand Down Expand Up @@ -326,8 +328,8 @@ static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index,
int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
int err;

voltage = clamp_val(voltage, 0, 0x3ff * nct7802_vmul[nr]);
voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]);
voltage = clamp_val(voltage, 0, 0x3ff);

mutex_lock(&data->access_lock);
err = regmap_write(data->regmap,
Expand Down Expand Up @@ -402,7 +404,7 @@ static ssize_t store_temp(struct device *dev, struct device_attribute *attr,
if (err < 0)
return err;

val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);

err = regmap_write(data->regmap, nr, val & 0xff);
return err ? : count;
Expand Down

0 comments on commit c0d04e9

Please sign in to comment.