hwmon: (tmp513) Fix division of negative numbers
BugLink: https://bugs.launchpad.net/bugs/2107449 [ Upstream commit e2c68cea431d65292b592c9f8446c918d45fcf78 ] Fix several issues with division of negative numbers in the tmp513 driver. The docs on the DIV_ROUND_CLOSEST macro explain that dividing a negative value by an unsigned type is undefined behavior. The driver was doing this in several places, i.e. data->shunt_uohms has type of u32. The actual "undefined" behavior is that it converts both values to unsigned before doing the division, for example: int ret = DIV_ROUND_CLOSEST(-100, 3U); results in ret == 1431655732 instead of -33. Furthermore the MILLI macro has a type of unsigned long. Multiplying a signed long by an unsigned long results in an unsigned long. So, we need to cast both MILLI and data data->shunt_uohms to long when using the DIV_ROUND_CLOSEST macro. Fixes:f07f9d2467("hwmon: (tmp513) Use SI constants from units.h") Fixes:59dfa75e5d("hwmon: Add driver for Texas Instruments TMP512/513 sensor chips.") Signed-off-by: David Lechner <dlechner@baylibre.com> Link: https://lore.kernel.org/r/20250114-fix-si-prefix-macro-sign-bugs-v1-1-696fd8d10f00@baylibre.com [groeck: Drop some continuation lines] Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
committed by
Stefan Bader
parent
7a4f7f51b2
commit
a3d0d71a1d
@@ -207,7 +207,8 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
||||
*val = sign_extend32(regval,
|
||||
reg == TMP51X_SHUNT_CURRENT_RESULT ?
|
||||
16 - tmp51x_get_pga_shift(data) : 15);
|
||||
*val = DIV_ROUND_CLOSEST(*val * 10 * MILLI, data->shunt_uohms);
|
||||
*val = DIV_ROUND_CLOSEST(*val * 10 * (long)MILLI, (long)data->shunt_uohms);
|
||||
|
||||
break;
|
||||
case TMP51X_BUS_VOLTAGE_RESULT:
|
||||
case TMP51X_BUS_VOLTAGE_H_LIMIT:
|
||||
@@ -223,7 +224,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
||||
case TMP51X_BUS_CURRENT_RESULT:
|
||||
// Current = (ShuntVoltage * CalibrationRegister) / 4096
|
||||
*val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua;
|
||||
*val = DIV_ROUND_CLOSEST(*val, MILLI);
|
||||
*val = DIV_ROUND_CLOSEST(*val, (long)MILLI);
|
||||
break;
|
||||
case TMP51X_LOCAL_TEMP_RESULT:
|
||||
case TMP51X_REMOTE_TEMP_RESULT_1:
|
||||
@@ -263,7 +264,7 @@ static int tmp51x_set_value(struct tmp51x_data *data, u8 reg, long val)
|
||||
* The user enter current value and we convert it to
|
||||
* voltage. 1lsb = 10uV
|
||||
*/
|
||||
val = DIV_ROUND_CLOSEST(val * data->shunt_uohms, 10 * MILLI);
|
||||
val = DIV_ROUND_CLOSEST(val * (long)data->shunt_uohms, 10 * (long)MILLI);
|
||||
max_val = U16_MAX >> tmp51x_get_pga_shift(data);
|
||||
regval = clamp_val(val, -max_val, max_val);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user