Commit edd11a943357 for kernel

commit edd11a94335747423569500a194c6eaa915f2963
Author: Guenter Roeck <linux@roeck-us.net>
Date:   Tue Aug 4 15:42:42 2026 -0700

    hwmon: (ltc4282) Avoid overflow in maximum power calculation

    During device initialization in ltc4282_set_max_limits(), the calculation
    of the maximum power limit can suffer from a 32-bit integer overflow.

    static int ltc4282_set_max_limits(struct ltc4282_state *st)
    {
        ...
        st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI,
                                          st->rsense) * st->vfs_out;
        ...
    }

    The result of DIV_ROUND_CLOSEST() evaluates to a 32-bit unsigned integer
    on 32-bit architectures. This result is then multiplied by st->vfs_out,
    which is a 16-bit unsigned integer. According to C promotion rules, since
    both operands are 32-bit or smaller, the multiplication is performed in
    32-bit precision.

    If the device is configured with a low sense resistor value via the device
    tree (for example, 100 nano-ohms, resulting in st->rsense = 1) and the
    voltage is high, the division result can reach 343,750,000 and st->vfs_out
    can be 33,280. The product of these values is approximately 11.44 trillion,
    which exceeds the maximum capacity of a 32-bit integer and overflows
    before being stored in st->power_max.

    This overflow causes a truncated value to be assigned to st->power_max and
    written to the hardware limit register. An incorrect maximum power limit
    can trigger spurious power-bad faults or alarms, which may lead to the
    shutdown of the monitored power rail.

    Avoid the problem by calculating and storing the maximum power using 64-bit
    variables.

    Reported-by: Sashiko <sashiko-bot@kernel.org>
    Fixes: cbc29538dbf7d ("hwmon: Add driver for LTC4282")
    Cc: Nuno Sa <nuno.sa@analog.com>
    Reviewed-by: Nuno Sá <nuno.sa@analog.com>
    Signed-off-by: Guenter Roeck <linux@roeck-us.net>

diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
index cc698803f8bf..bb7f6727c44d 100644
--- a/drivers/hwmon/ltc4282.c
+++ b/drivers/hwmon/ltc4282.c
@@ -137,7 +137,7 @@ struct ltc4282_state {
 	 */
 	struct ltc4282_cache in0_1_cache[LTC4282_CHAN_VGPIO];
 	u32 vsense_max;
-	long power_max;
+	s64 power_max;
 	u32 rsense;
 	u16 vdd;
 	u16 vfs_out;
@@ -613,13 +613,12 @@ static int ltc4282_read(struct device *dev, enum hwmon_sensor_types type,
 }

 static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
-				    long val)
+				    s64 val)
 {
 	u32 power;
 	u64 temp;

-	if (val > st->power_max)
-		val = st->power_max;
+	val = clamp(val, 0, st->power_max);

 	temp = val * int_pow(U8_MAX, 2) * st->rsense;
 	power = DIV64_U64_ROUND_CLOSEST(temp,
@@ -629,7 +628,7 @@ static int ltc4282_write_power_byte(const struct ltc4282_state *st, u32 reg,
 }

 static int ltc4282_write_power_word(const struct ltc4282_state *st, u32 reg,
-				    long val)
+				    u64 val)
 {
 	u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2;
 	__be16 __raw;
@@ -1222,7 +1221,8 @@ static int ltc4282_set_max_limits(struct ltc4282_state *st)
 		return ret;

 	/* Power is given by ISENSE * Vout. */
-	st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out;
+	st->power_max = DIV_ROUND_CLOSEST_ULL((u64)st->vsense_max * DECA * MILLI,
+					      st->rsense) * st->vfs_out;
 	ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max);
 	if (ret)
 		return ret;