diff options
author | Guenter Roeck <linux@roeck-us.net> | 2016-06-24 22:41:57 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2016-06-27 21:58:04 -0400 |
commit | 9ad0df1adac20d694fbb8e7cb7bac04e0645a927 (patch) | |
tree | 49f518ce469dd8fc3636d65ffccd28899741c098 | |
parent | 51b8c2cd92f1b59657a13339dffcca79c76126d1 (diff) |
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>
-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 d055b6a2266b..e6b49500c52a 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c | |||
@@ -95,7 +95,7 @@ static const unsigned int register_channel[] = { | |||
95 | struct ina3221_data { | 95 | struct ina3221_data { |
96 | struct regmap *regmap; | 96 | struct regmap *regmap; |
97 | struct regmap_field *fields[F_MAX_FIELDS]; | 97 | struct regmap_field *fields[F_MAX_FIELDS]; |
98 | unsigned int shunt_resistors[INA3221_NUM_CHANNELS]; | 98 | int shunt_resistors[INA3221_NUM_CHANNELS]; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, | 101 | 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, | |||
155 | struct ina3221_data *ina = dev_get_drvdata(dev); | 155 | struct ina3221_data *ina = dev_get_drvdata(dev); |
156 | unsigned int reg = sd_attr->index; | 156 | unsigned int reg = sd_attr->index; |
157 | unsigned int channel = register_channel[reg]; | 157 | unsigned int channel = register_channel[reg]; |
158 | unsigned int resistance_uo = ina->shunt_resistors[channel]; | 158 | int resistance_uo = ina->shunt_resistors[channel]; |
159 | int val, current_ma, voltage_nv, ret; | 159 | int val, current_ma, voltage_nv, ret; |
160 | 160 | ||
161 | ret = ina3221_read_value(ina, reg, &val); | 161 | ret = ina3221_read_value(ina, reg, &val); |
@@ -176,7 +176,7 @@ static ssize_t ina3221_set_current(struct device *dev, | |||
176 | struct ina3221_data *ina = dev_get_drvdata(dev); | 176 | struct ina3221_data *ina = dev_get_drvdata(dev); |
177 | unsigned int reg = sd_attr->index; | 177 | unsigned int reg = sd_attr->index; |
178 | unsigned int channel = register_channel[reg]; | 178 | unsigned int channel = register_channel[reg]; |
179 | unsigned int resistance_uo = ina->shunt_resistors[channel]; | 179 | int resistance_uo = ina->shunt_resistors[channel]; |
180 | int val, current_ma, voltage_uv, ret; | 180 | int val, current_ma, voltage_uv, ret; |
181 | 181 | ||
182 | ret = kstrtoint(buf, 0, ¤t_ma); | 182 | ret = kstrtoint(buf, 0, ¤t_ma); |
@@ -223,15 +223,14 @@ static ssize_t ina3221_set_shunt(struct device *dev, | |||
223 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | 223 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); |
224 | struct ina3221_data *ina = dev_get_drvdata(dev); | 224 | struct ina3221_data *ina = dev_get_drvdata(dev); |
225 | unsigned int channel = sd_attr->index; | 225 | unsigned int channel = sd_attr->index; |
226 | unsigned int val; | 226 | int val; |
227 | int ret; | 227 | int ret; |
228 | 228 | ||
229 | ret = kstrtouint(buf, 0, &val); | 229 | ret = kstrtoint(buf, 0, &val); |
230 | if (ret) | 230 | if (ret) |
231 | return ret; | 231 | return ret; |
232 | 232 | ||
233 | if (val == 0) | 233 | val = clamp_val(val, 1, INT_MAX); |
234 | return -EINVAL; | ||
235 | 234 | ||
236 | ina->shunt_resistors[channel] = val; | 235 | ina->shunt_resistors[channel] = val; |
237 | 236 | ||