Takashi Iwai 828ccf
From 1eda52334e6d13eb1a85f713ce06dd39342b5020 Mon Sep 17 00:00:00 2001
Takashi Iwai 828ccf
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Takashi Iwai 828ccf
Date: Tue, 15 Dec 2020 10:20:30 +0100
Takashi Iwai 828ccf
Subject: [PATCH] hwmon: (pwm-fan) Ensure that calculation doesn't discard big period values
Takashi Iwai 828ccf
Mime-version: 1.0
Takashi Iwai 828ccf
Content-type: text/plain; charset=UTF-8
Takashi Iwai 828ccf
Content-transfer-encoding: 8bit
Takashi Iwai 828ccf
Git-commit: 1eda52334e6d13eb1a85f713ce06dd39342b5020
Takashi Iwai 828ccf
Patch-mainline: v5.11-rc3
Takashi Iwai 828ccf
References: git-fixes
Takashi Iwai 828ccf
Takashi Iwai 828ccf
With MAX_PWM being defined to 255 the code
Takashi Iwai 828ccf
Takashi Iwai 828ccf
	unsigned long period;
Takashi Iwai 828ccf
	...
Takashi Iwai 828ccf
	period = ctx->pwm->args.period;
Takashi Iwai 828ccf
	state.duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
Takashi Iwai 828ccf
Takashi Iwai 828ccf
calculates a too small value for duty_cycle if the configured period is
Takashi Iwai 828ccf
big (either by discarding the 64 bit value ctx->pwm->args.period or by
Takashi Iwai 828ccf
overflowing the multiplication). As this results in a too slow fan and
Takashi Iwai 828ccf
so maybe an overheating machine better be safe than sorry and error out
Takashi Iwai 828ccf
in .probe.
Takashi Iwai 828ccf
Takashi Iwai 828ccf
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Takashi Iwai 828ccf
Link: https://lore.kernel.org/r/20201215092031.152243-1-u.kleine-koenig@pengutronix.de
Takashi Iwai 828ccf
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Takashi Iwai 828ccf
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 828ccf
Takashi Iwai 828ccf
---
Takashi Iwai 828ccf
 drivers/hwmon/pwm-fan.c | 12 +++++++++++-
Takashi Iwai 828ccf
 1 file changed, 11 insertions(+), 1 deletion(-)
Takashi Iwai 828ccf
Takashi Iwai 828ccf
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
Takashi Iwai 828ccf
index 777439f48c14..111a91dc6b79 100644
Takashi Iwai 828ccf
--- a/drivers/hwmon/pwm-fan.c
Takashi Iwai 828ccf
+++ b/drivers/hwmon/pwm-fan.c
Takashi Iwai 828ccf
@@ -334,8 +334,18 @@ static int pwm_fan_probe(struct platform_device *pdev)
Takashi Iwai 828ccf
 
Takashi Iwai 828ccf
 	ctx->pwm_value = MAX_PWM;
Takashi Iwai 828ccf
 
Takashi Iwai 828ccf
-	/* Set duty cycle to maximum allowed and enable PWM output */
Takashi Iwai 828ccf
 	pwm_init_state(ctx->pwm, &state);
Takashi Iwai 828ccf
+	/*
Takashi Iwai 828ccf
+	 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned
Takashi Iwai 828ccf
+	 * long. Check this here to prevent the fan running at a too low
Takashi Iwai 828ccf
+	 * frequency.
Takashi Iwai 828ccf
+	 */
Takashi Iwai 828ccf
+	if (state.period > ULONG_MAX / MAX_PWM + 1) {
Takashi Iwai 828ccf
+		dev_err(dev, "Configured period too big\n");
Takashi Iwai 828ccf
+		return -EINVAL;
Takashi Iwai 828ccf
+	}
Takashi Iwai 828ccf
+
Takashi Iwai 828ccf
+	/* Set duty cycle to maximum allowed and enable PWM output */
Takashi Iwai 828ccf
 	state.duty_cycle = ctx->pwm->args.period - 1;
Takashi Iwai 828ccf
 	state.enabled = true;
Takashi Iwai 828ccf
 
Takashi Iwai 828ccf
-- 
Takashi Iwai 828ccf
2.26.2
Takashi Iwai 828ccf