From: Chunyan Zhang <[email protected]>
The patch 2/2 fixes an overflow error by changing to 64-bit divide operations.
In order to avoid compile error on 32-bit architectures, this patchset
also introduced a new 64-bit helper in patch 1/2.
Changes since v1: (https://lkml.org/lkml/2020/7/17/63)
- Added new help macro DIV_S64_ROUND_CLOSEST;
- Fixed an error reported by kernel test robot <[email protected]>.
Chunyan Zhang (2):
math64: New DIV_S64_ROUND_CLOSEST helper
power: supply: sc27xx: prevent adc * 1000 from overflow
drivers/power/supply/sc27xx_fuel_gauge.c | 9 +++++----
include/linux/math64.h | 19 +++++++++++++++++++
2 files changed, 24 insertions(+), 4 deletions(-)
--
2.20.1
From: Chunyan Zhang <[email protected]>
The input parameter is int type, cause adc * 1000 could overflow.
Change to use s64 to avoid this issue.
Signed-off-by: Chen Yongzhi <[email protected]>
Signed-off-by: Chunyan Zhang <[email protected]>
---
drivers/power/supply/sc27xx_fuel_gauge.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
index be42e814ea34..9c627618c224 100644
--- a/drivers/power/supply/sc27xx_fuel_gauge.c
+++ b/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -5,6 +5,7 @@
#include <linux/iio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
@@ -133,14 +134,14 @@ static const char * const sc27xx_charger_supply_name[] = {
"sc2723_charger",
};
-static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, int adc)
+static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, s64 adc)
{
- return DIV_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
+ return DIV_S64_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
}
-static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, int adc)
+static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, s64 adc)
{
- return DIV_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
+ return DIV_S64_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
}
static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol)
--
2.20.1
From: Chunyan Zhang <[email protected]>
Provide DIV_S64_ROUND_CLOSEST helper which uses div_s64 to perform
division rounded to the closest integer using signed 64bit
dividend and signed 32bit divisor.
Signed-off-by: Chunyan Zhang <[email protected]>
---
include/linux/math64.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/include/linux/math64.h b/include/linux/math64.h
index 11a267413e8e..cd0693989436 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -279,4 +279,23 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
#define DIV64_U64_ROUND_CLOSEST(dividend, divisor) \
({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
+/*
+ * DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ *
+ * Divide signed 64bit dividend by signed 32bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV_S64_ROUND_CLOSEST(dividend, divisor)( \
+{ \
+ s64 __x = (dividend); \
+ s32 __d = (divisor); \
+ ((__x > 0) == (__d > 0)) ? \
+ div_s64((__x + (__d / 2)), __d) : \
+ div_s64((__x - (__d / 2)), __d); \
+} \
+)
#endif /* _LINUX_MATH64_H */
--
2.20.1
Hi,
On Fri, Jul 24, 2020 at 08:21:46PM +0800, Chunyan Zhang wrote:
> From: Chunyan Zhang <[email protected]>
>
> The patch 2/2 fixes an overflow error by changing to 64-bit divide operations.
> In order to avoid compile error on 32-bit architectures, this patchset
> also introduced a new 64-bit helper in patch 1/2.
>
> Changes since v1: (https://lkml.org/lkml/2020/7/17/63)
> - Added new help macro DIV_S64_ROUND_CLOSEST;
> - Fixed an error reported by kernel test robot <[email protected]>.
>
> Chunyan Zhang (2):
> math64: New DIV_S64_ROUND_CLOSEST helper
> power: supply: sc27xx: prevent adc * 1000 from overflow
>
> drivers/power/supply/sc27xx_fuel_gauge.c | 9 +++++----
> include/linux/math64.h | 19 +++++++++++++++++++
> 2 files changed, 24 insertions(+), 4 deletions(-)
Thanks, queued.
-- Sebastian