Commit 9ad0df1a authored by Guenter Roeck's avatar Guenter Roeck

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: default avatarAndrew F. Davis <afd@ti.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 51b8c2cd
...@@ -95,7 +95,7 @@ static const unsigned int register_channel[] = { ...@@ -95,7 +95,7 @@ static const unsigned int register_channel[] = {
struct ina3221_data { struct ina3221_data {
struct regmap *regmap; struct regmap *regmap;
struct regmap_field *fields[F_MAX_FIELDS]; 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, 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,7 +155,7 @@ static ssize_t ina3221_show_current(struct device *dev,
struct ina3221_data *ina = dev_get_drvdata(dev); struct ina3221_data *ina = dev_get_drvdata(dev);
unsigned int reg = sd_attr->index; unsigned int reg = sd_attr->index;
unsigned int channel = register_channel[reg]; 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; int val, current_ma, voltage_nv, ret;
ret = ina3221_read_value(ina, reg, &val); ret = ina3221_read_value(ina, reg, &val);
...@@ -176,7 +176,7 @@ static ssize_t ina3221_set_current(struct device *dev, ...@@ -176,7 +176,7 @@ static ssize_t ina3221_set_current(struct device *dev,
struct ina3221_data *ina = dev_get_drvdata(dev); struct ina3221_data *ina = dev_get_drvdata(dev);
unsigned int reg = sd_attr->index; unsigned int reg = sd_attr->index;
unsigned int channel = register_channel[reg]; 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; int val, current_ma, voltage_uv, ret;
ret = kstrtoint(buf, 0, &current_ma); ret = kstrtoint(buf, 0, &current_ma);
...@@ -223,15 +223,14 @@ static ssize_t ina3221_set_shunt(struct device *dev, ...@@ -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 sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
struct ina3221_data *ina = dev_get_drvdata(dev); struct ina3221_data *ina = dev_get_drvdata(dev);
unsigned int channel = sd_attr->index; unsigned int channel = sd_attr->index;
unsigned int val; int val;
int ret; int ret;
ret = kstrtouint(buf, 0, &val); ret = kstrtoint(buf, 0, &val);
if (ret) if (ret)
return ret; return ret;
if (val == 0) val = clamp_val(val, 1, INT_MAX);
return -EINVAL;
ina->shunt_resistors[channel] = val; ina->shunt_resistors[channel] = val;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment