Skip to content

Commit 8ba75b2

Browse files
Krellangroeck
authored andcommitted
hwmon: (pmbus/core) Use s64 instead of long for calculations
Using s64 type, instead of long type, for internal calculations and for the sysfs interface. This allows 64-bit values to appear correctly on 32-bit kernels. As wattage is reported in microwatts, monitoring a power supply over 2KW requires this. Although it may seem unlikely to run a 32-bit kernel on such a large machine, enterprise servers often include a BMC, and the BMC might be running a 32-bit kernel. Signed-off-by: Josh Lehan <[email protected]> [groeck: Removed Change-Id and other tags, reformatted description] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 5c9353f commit 8ba75b2

File tree

1 file changed

+31
-35
lines changed

1 file changed

+31
-35
lines changed

drivers/hwmon/pmbus/pmbus_core.c

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -628,12 +628,12 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
628628
* Convert linear sensor values to milli- or micro-units
629629
* depending on sensor type.
630630
*/
631-
static long pmbus_reg2data_linear(struct pmbus_data *data,
632-
struct pmbus_sensor *sensor)
631+
static s64 pmbus_reg2data_linear(struct pmbus_data *data,
632+
struct pmbus_sensor *sensor)
633633
{
634634
s16 exponent;
635635
s32 mantissa;
636-
long val;
636+
s64 val;
637637

638638
if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */
639639
exponent = data->exponent[sensor->page];
@@ -647,11 +647,11 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
647647

648648
/* scale result to milli-units for all sensors except fans */
649649
if (sensor->class != PSC_FAN)
650-
val = val * 1000L;
650+
val = val * 1000LL;
651651

652652
/* scale result to micro-units for power sensors */
653653
if (sensor->class == PSC_POWER)
654-
val = val * 1000L;
654+
val = val * 1000LL;
655655

656656
if (exponent >= 0)
657657
val <<= exponent;
@@ -665,8 +665,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
665665
* Convert direct sensor values to milli- or micro-units
666666
* depending on sensor type.
667667
*/
668-
static long pmbus_reg2data_direct(struct pmbus_data *data,
669-
struct pmbus_sensor *sensor)
668+
static s64 pmbus_reg2data_direct(struct pmbus_data *data,
669+
struct pmbus_sensor *sensor)
670670
{
671671
s64 b, val = (s16)sensor->data;
672672
s32 m, R;
@@ -702,15 +702,15 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
702702
}
703703

704704
val = div_s64(val - b, m);
705-
return clamp_val(val, LONG_MIN, LONG_MAX);
705+
return val;
706706
}
707707

708708
/*
709709
* Convert VID sensor values to milli- or micro-units
710710
* depending on sensor type.
711711
*/
712-
static long pmbus_reg2data_vid(struct pmbus_data *data,
713-
struct pmbus_sensor *sensor)
712+
static s64 pmbus_reg2data_vid(struct pmbus_data *data,
713+
struct pmbus_sensor *sensor)
714714
{
715715
long val = sensor->data;
716716
long rv = 0;
@@ -740,9 +740,9 @@ static long pmbus_reg2data_vid(struct pmbus_data *data,
740740
return rv;
741741
}
742742

743-
static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
743+
static s64 pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
744744
{
745-
long val;
745+
s64 val;
746746

747747
if (!sensor->convert)
748748
return sensor->data;
@@ -766,7 +766,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
766766
#define MIN_MANTISSA (511 * 1000)
767767

768768
static u16 pmbus_data2reg_linear(struct pmbus_data *data,
769-
struct pmbus_sensor *sensor, long val)
769+
struct pmbus_sensor *sensor, s64 val)
770770
{
771771
s16 exponent = 0, mantissa;
772772
bool negative = false;
@@ -788,8 +788,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
788788
val <<= -data->exponent[sensor->page];
789789
else
790790
val >>= data->exponent[sensor->page];
791-
val = DIV_ROUND_CLOSEST(val, 1000);
792-
return val & 0xffff;
791+
val = DIV_ROUND_CLOSEST_ULL(val, 1000);
792+
return clamp_val(val, 0, 0xffff);
793793
}
794794

795795
if (val < 0) {
@@ -799,14 +799,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
799799

800800
/* Power is in uW. Convert to mW before converting. */
801801
if (sensor->class == PSC_POWER)
802-
val = DIV_ROUND_CLOSEST(val, 1000L);
802+
val = DIV_ROUND_CLOSEST_ULL(val, 1000);
803803

804804
/*
805805
* For simplicity, convert fan data to milli-units
806806
* before calculating the exponent.
807807
*/
808808
if (sensor->class == PSC_FAN)
809-
val = val * 1000;
809+
val = val * 1000LL;
810810

811811
/* Reduce large mantissa until it fits into 10 bit */
812812
while (val >= MAX_MANTISSA && exponent < 15) {
@@ -820,11 +820,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
820820
}
821821

822822
/* Convert mantissa from milli-units to units */
823-
mantissa = DIV_ROUND_CLOSEST(val, 1000);
824-
825-
/* Ensure that resulting number is within range */
826-
if (mantissa > 0x3ff)
827-
mantissa = 0x3ff;
823+
mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
828824

829825
/* restore sign */
830826
if (negative)
@@ -835,9 +831,9 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
835831
}
836832

837833
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
838-
struct pmbus_sensor *sensor, long val)
834+
struct pmbus_sensor *sensor, s64 val)
839835
{
840-
s64 b, val64 = val;
836+
s64 b;
841837
s32 m, R;
842838

843839
m = data->info->m[sensor->class];
@@ -855,30 +851,30 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
855851
R -= 3; /* Adjust R and b for data in milli-units */
856852
b *= 1000;
857853
}
858-
val64 = val64 * m + b;
854+
val = val * m + b;
859855

860856
while (R > 0) {
861-
val64 *= 10;
857+
val *= 10;
862858
R--;
863859
}
864860
while (R < 0) {
865-
val64 = div_s64(val64 + 5LL, 10L); /* round closest */
861+
val = div_s64(val + 5LL, 10L); /* round closest */
866862
R++;
867863
}
868864

869-
return (u16)clamp_val(val64, S16_MIN, S16_MAX);
865+
return (u16)clamp_val(val, S16_MIN, S16_MAX);
870866
}
871867

872868
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
873-
struct pmbus_sensor *sensor, long val)
869+
struct pmbus_sensor *sensor, s64 val)
874870
{
875871
val = clamp_val(val, 500, 1600);
876872

877-
return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
873+
return 2 + DIV_ROUND_CLOSEST_ULL((1600LL - val) * 100LL, 625);
878874
}
879875

880876
static u16 pmbus_data2reg(struct pmbus_data *data,
881-
struct pmbus_sensor *sensor, long val)
877+
struct pmbus_sensor *sensor, s64 val)
882878
{
883879
u16 regval;
884880

@@ -944,7 +940,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
944940
WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
945941
return 0;
946942
} else {
947-
long v1, v2;
943+
s64 v1, v2;
948944

949945
if (s1->data < 0)
950946
return s1->data;
@@ -981,7 +977,7 @@ static ssize_t pmbus_show_sensor(struct device *dev,
981977
if (sensor->data < 0)
982978
return sensor->data;
983979

984-
return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
980+
return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
985981
}
986982

987983
static ssize_t pmbus_set_sensor(struct device *dev,
@@ -992,11 +988,11 @@ static ssize_t pmbus_set_sensor(struct device *dev,
992988
struct pmbus_data *data = i2c_get_clientdata(client);
993989
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
994990
ssize_t rv = count;
995-
long val = 0;
991+
s64 val;
996992
int ret;
997993
u16 regval;
998994

999-
if (kstrtol(buf, 10, &val) < 0)
995+
if (kstrtos64(buf, 10, &val) < 0)
1000996
return -EINVAL;
1001997

1002998
mutex_lock(&data->update_lock);

0 commit comments

Comments
 (0)