diff mbox series

hwmon: (pmbus/core) Use s64 instead of long for calculations

Message ID 20200626001343.162071-1-krellan@google.com (mailing list archive)
State Accepted
Headers show
Series hwmon: (pmbus/core) Use s64 instead of long for calculations | expand

Commit Message

Josh Lehan June 26, 2020, 12:13 a.m. UTC
Using s64 type, instead of long type,
for internal calculations and 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....

Effort: semitruck
Google-Bug-Id: 159769574
Signed-off-by: Josh Lehan <krellan@google.com>
Change-Id: If89882e20387454189b2ebe20c793d4cf166dfa8
---
 drivers/hwmon/pmbus/pmbus_core.c | 66 +++++++++++++++-----------------
 1 file changed, 31 insertions(+), 35 deletions(-)

Comments

Guenter Roeck June 26, 2020, 1:06 a.m. UTC | #1
On Thu, Jun 25, 2020 at 05:13:43PM -0700, Josh Lehan wrote:
> Using s64 type, instead of long type,
> for internal calculations and 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....
> 
> Effort: semitruck
> Google-Bug-Id: 159769574
> Signed-off-by: Josh Lehan <krellan@google.com>
> Change-Id: If89882e20387454189b2ebe20c793d4cf166dfa8

Applied to hwmon-next after removing irrelevant tags.

Thanks,
Guenter

> ---
>  drivers/hwmon/pmbus/pmbus_core.c | 66 +++++++++++++++-----------------
>  1 file changed, 31 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index 51eb6d56d29c..52bf71ef5ac4 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -646,12 +646,12 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
>   * Convert linear sensor values to milli- or micro-units
>   * depending on sensor type.
>   */
> -static long pmbus_reg2data_linear(struct pmbus_data *data,
> -				  struct pmbus_sensor *sensor)
> +static s64 pmbus_reg2data_linear(struct pmbus_data *data,
> +				 struct pmbus_sensor *sensor)
>  {
>  	s16 exponent;
>  	s32 mantissa;
> -	long val;
> +	s64 val;
>  
>  	if (sensor->class == PSC_VOLTAGE_OUT) {	/* LINEAR16 */
>  		exponent = data->exponent[sensor->page];
> @@ -665,11 +665,11 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
>  
>  	/* scale result to milli-units for all sensors except fans */
>  	if (sensor->class != PSC_FAN)
> -		val = val * 1000L;
> +		val = val * 1000LL;
>  
>  	/* scale result to micro-units for power sensors */
>  	if (sensor->class == PSC_POWER)
> -		val = val * 1000L;
> +		val = val * 1000LL;
>  
>  	if (exponent >= 0)
>  		val <<= exponent;
> @@ -683,8 +683,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
>   * Convert direct sensor values to milli- or micro-units
>   * depending on sensor type.
>   */
> -static long pmbus_reg2data_direct(struct pmbus_data *data,
> -				  struct pmbus_sensor *sensor)
> +static s64 pmbus_reg2data_direct(struct pmbus_data *data,
> +				 struct pmbus_sensor *sensor)
>  {
>  	s64 b, val = (s16)sensor->data;
>  	s32 m, R;
> @@ -720,15 +720,15 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
>  	}
>  
>  	val = div_s64(val - b, m);
> -	return clamp_val(val, LONG_MIN, LONG_MAX);
> +	return val;
>  }
>  
>  /*
>   * Convert VID sensor values to milli- or micro-units
>   * depending on sensor type.
>   */
> -static long pmbus_reg2data_vid(struct pmbus_data *data,
> -			       struct pmbus_sensor *sensor)
> +static s64 pmbus_reg2data_vid(struct pmbus_data *data,
> +			      struct pmbus_sensor *sensor)
>  {
>  	long val = sensor->data;
>  	long rv = 0;
> @@ -750,9 +750,9 @@ static long pmbus_reg2data_vid(struct pmbus_data *data,
>  	return rv;
>  }
>  
> -static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
> +static s64 pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
>  {
> -	long val;
> +	s64 val;
>  
>  	if (!sensor->convert)
>  		return sensor->data;
> @@ -776,7 +776,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
>  #define MIN_MANTISSA	(511 * 1000)
>  
>  static u16 pmbus_data2reg_linear(struct pmbus_data *data,
> -				 struct pmbus_sensor *sensor, long val)
> +				 struct pmbus_sensor *sensor, s64 val)
>  {
>  	s16 exponent = 0, mantissa;
>  	bool negative = false;
> @@ -798,8 +798,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
>  			val <<= -data->exponent[sensor->page];
>  		else
>  			val >>= data->exponent[sensor->page];
> -		val = DIV_ROUND_CLOSEST(val, 1000);
> -		return val & 0xffff;
> +		val = DIV_ROUND_CLOSEST_ULL(val, 1000);
> +		return clamp_val(val, 0, 0xffff);
>  	}
>  
>  	if (val < 0) {
> @@ -809,14 +809,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
>  
>  	/* Power is in uW. Convert to mW before converting. */
>  	if (sensor->class == PSC_POWER)
> -		val = DIV_ROUND_CLOSEST(val, 1000L);
> +		val = DIV_ROUND_CLOSEST_ULL(val, 1000);
>  
>  	/*
>  	 * For simplicity, convert fan data to milli-units
>  	 * before calculating the exponent.
>  	 */
>  	if (sensor->class == PSC_FAN)
> -		val = val * 1000;
> +		val = val * 1000LL;
>  
>  	/* Reduce large mantissa until it fits into 10 bit */
>  	while (val >= MAX_MANTISSA && exponent < 15) {
> @@ -830,11 +830,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
>  	}
>  
>  	/* Convert mantissa from milli-units to units */
> -	mantissa = DIV_ROUND_CLOSEST(val, 1000);
> -
> -	/* Ensure that resulting number is within range */
> -	if (mantissa > 0x3ff)
> -		mantissa = 0x3ff;
> +	mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
>  
>  	/* restore sign */
>  	if (negative)
> @@ -845,9 +841,9 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
>  }
>  
>  static u16 pmbus_data2reg_direct(struct pmbus_data *data,
> -				 struct pmbus_sensor *sensor, long val)
> +				 struct pmbus_sensor *sensor, s64 val)
>  {
> -	s64 b, val64 = val;
> +	s64 b;
>  	s32 m, R;
>  
>  	m = data->info->m[sensor->class];
> @@ -865,30 +861,30 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
>  		R -= 3;		/* Adjust R and b for data in milli-units */
>  		b *= 1000;
>  	}
> -	val64 = val64 * m + b;
> +	val = val * m + b;
>  
>  	while (R > 0) {
> -		val64 *= 10;
> +		val *= 10;
>  		R--;
>  	}
>  	while (R < 0) {
> -		val64 = div_s64(val64 + 5LL, 10L);  /* round closest */
> +		val = div_s64(val + 5LL, 10L);  /* round closest */
>  		R++;
>  	}
>  
> -	return (u16)clamp_val(val64, S16_MIN, S16_MAX);
> +	return (u16)clamp_val(val, S16_MIN, S16_MAX);
>  }
>  
>  static u16 pmbus_data2reg_vid(struct pmbus_data *data,
> -			      struct pmbus_sensor *sensor, long val)
> +			      struct pmbus_sensor *sensor, s64 val)
>  {
>  	val = clamp_val(val, 500, 1600);
>  
> -	return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
> +	return 2 + DIV_ROUND_CLOSEST_ULL((1600LL - val) * 100LL, 625);
>  }
>  
>  static u16 pmbus_data2reg(struct pmbus_data *data,
> -			  struct pmbus_sensor *sensor, long val)
> +			  struct pmbus_sensor *sensor, s64 val)
>  {
>  	u16 regval;
>  
> @@ -954,7 +950,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
>  		WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
>  		return 0;
>  	} else {
> -		long v1, v2;
> +		s64 v1, v2;
>  
>  		if (s1->data < 0)
>  			return s1->data;
> @@ -991,7 +987,7 @@ static ssize_t pmbus_show_sensor(struct device *dev,
>  	if (sensor->data < 0)
>  		return sensor->data;
>  
> -	return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
> +	return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
>  }
>  
>  static ssize_t pmbus_set_sensor(struct device *dev,
> @@ -1002,11 +998,11 @@ static ssize_t pmbus_set_sensor(struct device *dev,
>  	struct pmbus_data *data = i2c_get_clientdata(client);
>  	struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
>  	ssize_t rv = count;
> -	long val = 0;
> +	s64 val;
>  	int ret;
>  	u16 regval;
>  
> -	if (kstrtol(buf, 10, &val) < 0)
> +	if (kstrtos64(buf, 10, &val) < 0)
>  		return -EINVAL;
>  
>  	mutex_lock(&data->update_lock);
> -- 
> 2.27.0.212.ge8ba1cc988-goog
>
diff mbox series

Patch

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 51eb6d56d29c..52bf71ef5ac4 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -646,12 +646,12 @@  static struct pmbus_data *pmbus_update_device(struct device *dev)
  * Convert linear sensor values to milli- or micro-units
  * depending on sensor type.
  */
-static long pmbus_reg2data_linear(struct pmbus_data *data,
-				  struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_linear(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
 {
 	s16 exponent;
 	s32 mantissa;
-	long val;
+	s64 val;
 
 	if (sensor->class == PSC_VOLTAGE_OUT) {	/* LINEAR16 */
 		exponent = data->exponent[sensor->page];
@@ -665,11 +665,11 @@  static long pmbus_reg2data_linear(struct pmbus_data *data,
 
 	/* scale result to milli-units for all sensors except fans */
 	if (sensor->class != PSC_FAN)
-		val = val * 1000L;
+		val = val * 1000LL;
 
 	/* scale result to micro-units for power sensors */
 	if (sensor->class == PSC_POWER)
-		val = val * 1000L;
+		val = val * 1000LL;
 
 	if (exponent >= 0)
 		val <<= exponent;
@@ -683,8 +683,8 @@  static long pmbus_reg2data_linear(struct pmbus_data *data,
  * Convert direct sensor values to milli- or micro-units
  * depending on sensor type.
  */
-static long pmbus_reg2data_direct(struct pmbus_data *data,
-				  struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_direct(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
 {
 	s64 b, val = (s16)sensor->data;
 	s32 m, R;
@@ -720,15 +720,15 @@  static long pmbus_reg2data_direct(struct pmbus_data *data,
 	}
 
 	val = div_s64(val - b, m);
-	return clamp_val(val, LONG_MIN, LONG_MAX);
+	return val;
 }
 
 /*
  * Convert VID sensor values to milli- or micro-units
  * depending on sensor type.
  */
-static long pmbus_reg2data_vid(struct pmbus_data *data,
-			       struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_vid(struct pmbus_data *data,
+			      struct pmbus_sensor *sensor)
 {
 	long val = sensor->data;
 	long rv = 0;
@@ -750,9 +750,9 @@  static long pmbus_reg2data_vid(struct pmbus_data *data,
 	return rv;
 }
 
-static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
 {
-	long val;
+	s64 val;
 
 	if (!sensor->convert)
 		return sensor->data;
@@ -776,7 +776,7 @@  static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
 #define MIN_MANTISSA	(511 * 1000)
 
 static u16 pmbus_data2reg_linear(struct pmbus_data *data,
-				 struct pmbus_sensor *sensor, long val)
+				 struct pmbus_sensor *sensor, s64 val)
 {
 	s16 exponent = 0, mantissa;
 	bool negative = false;
@@ -798,8 +798,8 @@  static u16 pmbus_data2reg_linear(struct pmbus_data *data,
 			val <<= -data->exponent[sensor->page];
 		else
 			val >>= data->exponent[sensor->page];
-		val = DIV_ROUND_CLOSEST(val, 1000);
-		return val & 0xffff;
+		val = DIV_ROUND_CLOSEST_ULL(val, 1000);
+		return clamp_val(val, 0, 0xffff);
 	}
 
 	if (val < 0) {
@@ -809,14 +809,14 @@  static u16 pmbus_data2reg_linear(struct pmbus_data *data,
 
 	/* Power is in uW. Convert to mW before converting. */
 	if (sensor->class == PSC_POWER)
-		val = DIV_ROUND_CLOSEST(val, 1000L);
+		val = DIV_ROUND_CLOSEST_ULL(val, 1000);
 
 	/*
 	 * For simplicity, convert fan data to milli-units
 	 * before calculating the exponent.
 	 */
 	if (sensor->class == PSC_FAN)
-		val = val * 1000;
+		val = val * 1000LL;
 
 	/* Reduce large mantissa until it fits into 10 bit */
 	while (val >= MAX_MANTISSA && exponent < 15) {
@@ -830,11 +830,7 @@  static u16 pmbus_data2reg_linear(struct pmbus_data *data,
 	}
 
 	/* Convert mantissa from milli-units to units */
-	mantissa = DIV_ROUND_CLOSEST(val, 1000);
-
-	/* Ensure that resulting number is within range */
-	if (mantissa > 0x3ff)
-		mantissa = 0x3ff;
+	mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
 
 	/* restore sign */
 	if (negative)
@@ -845,9 +841,9 @@  static u16 pmbus_data2reg_linear(struct pmbus_data *data,
 }
 
 static u16 pmbus_data2reg_direct(struct pmbus_data *data,
-				 struct pmbus_sensor *sensor, long val)
+				 struct pmbus_sensor *sensor, s64 val)
 {
-	s64 b, val64 = val;
+	s64 b;
 	s32 m, R;
 
 	m = data->info->m[sensor->class];
@@ -865,30 +861,30 @@  static u16 pmbus_data2reg_direct(struct pmbus_data *data,
 		R -= 3;		/* Adjust R and b for data in milli-units */
 		b *= 1000;
 	}
-	val64 = val64 * m + b;
+	val = val * m + b;
 
 	while (R > 0) {
-		val64 *= 10;
+		val *= 10;
 		R--;
 	}
 	while (R < 0) {
-		val64 = div_s64(val64 + 5LL, 10L);  /* round closest */
+		val = div_s64(val + 5LL, 10L);  /* round closest */
 		R++;
 	}
 
-	return (u16)clamp_val(val64, S16_MIN, S16_MAX);
+	return (u16)clamp_val(val, S16_MIN, S16_MAX);
 }
 
 static u16 pmbus_data2reg_vid(struct pmbus_data *data,
-			      struct pmbus_sensor *sensor, long val)
+			      struct pmbus_sensor *sensor, s64 val)
 {
 	val = clamp_val(val, 500, 1600);
 
-	return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
+	return 2 + DIV_ROUND_CLOSEST_ULL((1600LL - val) * 100LL, 625);
 }
 
 static u16 pmbus_data2reg(struct pmbus_data *data,
-			  struct pmbus_sensor *sensor, long val)
+			  struct pmbus_sensor *sensor, s64 val)
 {
 	u16 regval;
 
@@ -954,7 +950,7 @@  static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
 		WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
 		return 0;
 	} else {
-		long v1, v2;
+		s64 v1, v2;
 
 		if (s1->data < 0)
 			return s1->data;
@@ -991,7 +987,7 @@  static ssize_t pmbus_show_sensor(struct device *dev,
 	if (sensor->data < 0)
 		return sensor->data;
 
-	return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
+	return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
 }
 
 static ssize_t pmbus_set_sensor(struct device *dev,
@@ -1002,11 +998,11 @@  static ssize_t pmbus_set_sensor(struct device *dev,
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
 	ssize_t rv = count;
-	long val = 0;
+	s64 val;
 	int ret;
 	u16 regval;
 
-	if (kstrtol(buf, 10, &val) < 0)
+	if (kstrtos64(buf, 10, &val) < 0)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);