aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-12-11 13:27:42 -0800
committerLee Jones <lee.jones@linaro.org>2020-07-31 09:54:12 +0100
commit8490f56ce46a982b1e49910041621c33c80cc9dd (patch)
tree469440b665f232fc74b40a5a23fdcf266b8954ba
parentd228ed42d7ea8b65d24b4efcf0b0d3aa4ff54761 (diff)
hwmon: (g762) Fix overflows and crash seen when writing limit attributesASB-2020-08-05_3.18
commit 4fccd4a1e8944033bcd7693ea4e8fb478cd2059a upstream. Fix overflows seen when writing into fan speed limit attributes. Also fix crash due to division by zero, seen when certain very large values (such as 2147483648, or 0x80000000) are written into fan speed limit attributes. Fixes: 594fbe713bf60 ("Add support for GMT G762/G763 PWM fan controllers") Cc: Arnaud Ebalard <arno@natisbad.org> Reviewed-by: Jean Delvare <jdelvare@suse.de> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Lee Jones <lee.jones@linaro.org> Change-Id: I81d93f8372b95749fb292a0f10f98e8fe6b3f3df
-rw-r--r--drivers/hwmon/g762.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 9b55e673b67c..977b4d795322 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -193,14 +193,17 @@ static inline unsigned int rpm_from_cnt(u8 cnt, u32 clk_freq, u16 p,
* Convert fan RPM value from sysfs into count value for fan controller
* register (FAN_SET_CNT).
*/
-static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p,
+static inline unsigned char cnt_from_rpm(unsigned long rpm, u32 clk_freq, u16 p,
u8 clk_div, u8 gear_mult)
{
- if (!rpm) /* to stop the fan, set cnt to 255 */
+ unsigned long f1 = clk_freq * 30 * gear_mult;
+ unsigned long f2 = p * clk_div;
+
+ if (!rpm) /* to stop the fan, set cnt to 255 */
return 0xff;
- return clamp_val(((clk_freq * 30 * gear_mult) / (rpm * p * clk_div)),
- 0, 255);
+ rpm = clamp_val(rpm, f1 / (255 * f2), ULONG_MAX / f2);
+ return DIV_ROUND_CLOSEST(f1, rpm * f2);
}
/* helper to grab and cache data, at most one time per second */