| From ed25161ace293001f185db4fd3798069dbddb462 Mon Sep 17 00:00:00 2001 |
| From: Guenter Roeck <linux@roeck-us.net> |
| Date: Sun, 4 Dec 2016 18:15:25 -0800 |
| Subject: [PATCH] hwmon: (nct7802) Fix overflows seen when writing into limit |
| attributes |
| |
| commit c0d04e9112ad59d73f23f3b0f6726c5e798dfcbf upstream. |
| |
| 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: 3434f3783580 ("hwmon: Driver for Nuvoton NCT7802Y") |
| Reviewed-by: Jean Delvare <jdelvare@suse.de> |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c |
| index 3ce33d244cc0..12b94b094c0d 100644 |
| --- a/drivers/hwmon/nct7802.c |
| +++ b/drivers/hwmon/nct7802.c |
| @@ -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; |
| |
| @@ -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, |
| @@ -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; |
| -- |
| 2.10.1 |
| |