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>
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 @@
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 @@
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 @@
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 @@
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;