diff options
author | Guenter Roeck <linux@roeck-us.net> | 2016-06-24 19:41:57 -0700 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2016-06-27 18:58:04 -0700 |
commit | 9ad0df1adac20d694fbb8e7cb7bac04e0645a927 (patch) | |
tree | 49f518ce469dd8fc3636d65ffccd28899741c098 /drivers/hwmon | |
parent | 51b8c2cd92f1b59657a13339dffcca79c76126d1 (diff) | |
download | op-kernel-dev-9ad0df1adac20d694fbb8e7cb7bac04e0645a927.zip op-kernel-dev-9ad0df1adac20d694fbb8e7cb7bac04e0645a927.tar.gz |
hwmon: (ina3221) Fix negative limits
The result of an integer divide by an unsigned is undefined.
This causes unexpected results when writing negative values
into the limit registers.
Maintain the shunt_resistors variables as signed integer to avoid
the problem. Also, for simplicity and ease of use, clamp shunt
resistor value on writes instead of rejecting bad values.
Cc: Andrew F. Davis <afd@ti.com>
Acked-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/ina3221.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index d055b6a..e6b4950 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -95,7 +95,7 @@ static const unsigned int register_channel[] = { struct ina3221_data { struct regmap *regmap; struct regmap_field *fields[F_MAX_FIELDS]; - unsigned int shunt_resistors[INA3221_NUM_CHANNELS]; + int shunt_resistors[INA3221_NUM_CHANNELS]; }; static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, @@ -155,7 +155,7 @@ static ssize_t ina3221_show_current(struct device *dev, struct ina3221_data *ina = dev_get_drvdata(dev); unsigned int reg = sd_attr->index; unsigned int channel = register_channel[reg]; - unsigned int resistance_uo = ina->shunt_resistors[channel]; + int resistance_uo = ina->shunt_resistors[channel]; int val, current_ma, voltage_nv, ret; ret = ina3221_read_value(ina, reg, &val); @@ -176,7 +176,7 @@ static ssize_t ina3221_set_current(struct device *dev, struct ina3221_data *ina = dev_get_drvdata(dev); unsigned int reg = sd_attr->index; unsigned int channel = register_channel[reg]; - unsigned int resistance_uo = ina->shunt_resistors[channel]; + int resistance_uo = ina->shunt_resistors[channel]; int val, current_ma, voltage_uv, ret; ret = kstrtoint(buf, 0, ¤t_ma); @@ -223,15 +223,14 @@ static ssize_t ina3221_set_shunt(struct device *dev, struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); struct ina3221_data *ina = dev_get_drvdata(dev); unsigned int channel = sd_attr->index; - unsigned int val; + int val; int ret; - ret = kstrtouint(buf, 0, &val); + ret = kstrtoint(buf, 0, &val); if (ret) return ret; - if (val == 0) - return -EINVAL; + val = clamp_val(val, 1, INT_MAX); ina->shunt_resistors[channel] = val; |