Skip to content

Commit e2c68ce

Browse files
dlechgroeck
authored andcommitted
hwmon: (tmp513) Fix division of negative numbers
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: f07f9d2 ("hwmon: (tmp513) Use SI constants from units.h") Fixes: 59dfa75 ("hwmon: Add driver for Texas Instruments TMP512/513 sensor chips.") Signed-off-by: David Lechner <[email protected]> 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 <[email protected]>
1 parent 5bc55a3 commit e2c68ce

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

drivers/hwmon/tmp513.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
207207
*val = sign_extend32(regval,
208208
reg == TMP51X_SHUNT_CURRENT_RESULT ?
209209
16 - tmp51x_get_pga_shift(data) : 15);
210-
*val = DIV_ROUND_CLOSEST(*val * 10 * MILLI, data->shunt_uohms);
210+
*val = DIV_ROUND_CLOSEST(*val * 10 * (long)MILLI, (long)data->shunt_uohms);
211+
211212
break;
212213
case TMP51X_BUS_VOLTAGE_RESULT:
213214
case TMP51X_BUS_VOLTAGE_H_LIMIT:
@@ -223,7 +224,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
223224
case TMP51X_BUS_CURRENT_RESULT:
224225
// Current = (ShuntVoltage * CalibrationRegister) / 4096
225226
*val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua;
226-
*val = DIV_ROUND_CLOSEST(*val, MILLI);
227+
*val = DIV_ROUND_CLOSEST(*val, (long)MILLI);
227228
break;
228229
case TMP51X_LOCAL_TEMP_RESULT:
229230
case TMP51X_REMOTE_TEMP_RESULT_1:
@@ -263,7 +264,7 @@ static int tmp51x_set_value(struct tmp51x_data *data, u8 reg, long val)
263264
* The user enter current value and we convert it to
264265
* voltage. 1lsb = 10uV
265266
*/
266-
val = DIV_ROUND_CLOSEST(val * data->shunt_uohms, 10 * MILLI);
267+
val = DIV_ROUND_CLOSEST(val * (long)data->shunt_uohms, 10 * (long)MILLI);
267268
max_val = U16_MAX >> tmp51x_get_pga_shift(data);
268269
regval = clamp_val(val, -max_val, max_val);
269270
break;

0 commit comments

Comments
 (0)