aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-12-04 21:15:25 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 05:39:26 -0500
commit81616a9f751e9b08a90d13c79e6ca73a74c4b446 (patch)
tree701d2bd8e4b8124d96f27c4da6ccbb1f50574669
parenta69a6ebd036a6c7edf89db09ca358927c158dbe4 (diff)
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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hwmon/nct7802.c8
1 files changed, 5 insertions, 3 deletions
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,
259 ret = 0; 259 ret = 0;
260 else if (ret) 260 else if (ret)
261 ret = DIV_ROUND_CLOSEST(1350000U, ret); 261 ret = DIV_ROUND_CLOSEST(1350000U, ret);
262 else
263 ret = 1350000U;
262abort: 264abort:
263 mutex_unlock(&data->access_lock); 265 mutex_unlock(&data->access_lock);
264 return ret; 266 return ret;
265} 267}
266 268
267static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low, 269static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low,
268 u8 reg_fan_high, unsigned int limit) 270 u8 reg_fan_high, unsigned long limit)
269{ 271{
270 int err; 272 int err;
271 273
@@ -326,8 +328,8 @@ static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index,
326 int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr]; 328 int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
327 int err; 329 int err;
328 330
331 voltage = clamp_val(voltage, 0, 0x3ff * nct7802_vmul[nr]);
329 voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]); 332 voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]);
330 voltage = clamp_val(voltage, 0, 0x3ff);
331 333
332 mutex_lock(&data->access_lock); 334 mutex_lock(&data->access_lock);
333 err = regmap_write(data->regmap, 335 err = regmap_write(data->regmap,
@@ -402,7 +404,7 @@ static ssize_t store_temp(struct device *dev, struct device_attribute *attr,
402 if (err < 0) 404 if (err < 0)
403 return err; 405 return err;
404 406
405 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127); 407 val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
406 408
407 err = regmap_write(data->regmap, nr, val & 0xff); 409 err = regmap_write(data->regmap, nr, val & 0xff);
408 return err ? : count; 410 return err ? : count;