Skip to content

Commit bd467e4

Browse files
rlippertgroeck
authored andcommitted
hwmon: (pmbus) Use 64bit math for DIRECT format values
Power values in the 100s of watt range can easily blow past 32bit math limits when processing everything in microwatts. Use 64bit math instead to avoid these issues on common 32bit ARM BMC platforms. Fixes: 442aba7 ("hwmon: PMBus device driver") Signed-off-by: Robert Lippert <rlippert@google.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent ed81cc6 commit bd467e4

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

drivers/hwmon/pmbus/pmbus_core.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <linux/debugfs.h>
2323
#include <linux/kernel.h>
24+
#include <linux/math64.h>
2425
#include <linux/module.h>
2526
#include <linux/init.h>
2627
#include <linux/err.h>
@@ -499,8 +500,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
499500
static long pmbus_reg2data_direct(struct pmbus_data *data,
500501
struct pmbus_sensor *sensor)
501502
{
502-
long val = (s16) sensor->data;
503-
long m, b, R;
503+
s64 b, val = (s16)sensor->data;
504+
s32 m, R;
504505

505506
m = data->info->m[sensor->class];
506507
b = data->info->b[sensor->class];
@@ -528,11 +529,12 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
528529
R--;
529530
}
530531
while (R < 0) {
531-
val = DIV_ROUND_CLOSEST(val, 10);
532+
val = div_s64(val + 5LL, 10L); /* round closest */
532533
R++;
533534
}
534535

535-
return (val - b) / m;
536+
val = div_s64(val - b, m);
537+
return clamp_val(val, LONG_MIN, LONG_MAX);
536538
}
537539

538540
/*
@@ -656,7 +658,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
656658
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
657659
struct pmbus_sensor *sensor, long val)
658660
{
659-
long m, b, R;
661+
s64 b, val64 = val;
662+
s32 m, R;
660663

661664
m = data->info->m[sensor->class];
662665
b = data->info->b[sensor->class];
@@ -673,18 +676,18 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
673676
R -= 3; /* Adjust R and b for data in milli-units */
674677
b *= 1000;
675678
}
676-
val = val * m + b;
679+
val64 = val64 * m + b;
677680

678681
while (R > 0) {
679-
val *= 10;
682+
val64 *= 10;
680683
R--;
681684
}
682685
while (R < 0) {
683-
val = DIV_ROUND_CLOSEST(val, 10);
686+
val64 = div_s64(val64 + 5LL, 10L); /* round closest */
684687
R++;
685688
}
686689

687-
return val;
690+
return (u16)clamp_val(val64, S16_MIN, S16_MAX);
688691
}
689692

690693
static u16 pmbus_data2reg_vid(struct pmbus_data *data,

0 commit comments

Comments
 (0)