aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-06-24 22:41:57 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-06-27 21:58:04 -0400
commit9ad0df1adac20d694fbb8e7cb7bac04e0645a927 (patch)
tree49f518ce469dd8fc3636d65ffccd28899741c098
parent51b8c2cd92f1b59657a13339dffcca79c76126d1 (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.c13
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[] = {
95struct ina3221_data { 95struct 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
101static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, 101static 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, &current_ma); 182 ret = kstrtoint(buf, 0, &current_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