Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

hwmon: (macsmc) Fix regressions in Apple Silicon SMC hwmon driver

The recently added macsmc-hwmon driver contained several critical
bugs in its sensor population logic and float conversion routines.

Specifically:
- The voltage sensor population loop used the wrong prefix ("volt-"
instead of "voltage-") and incorrectly assigned sensors to the
temperature sensor array (hwmon->temp.sensors) instead of the
voltage sensor array (hwmon->volt.sensors). This would lead to
out-of-bounds memory access or data corruption when both temperature
and voltage sensors were present.
- The float conversion in macsmc_hwmon_write_f32() had flawed exponent
logic for values >= 2^24 and lacked masking for the mantissa, which
could lead to incorrect values being written to the SMC.

Fix these issues to ensure correct sensor registration and reliable
manual fan control.

Confirm that the reported overflow in FIELD_PREP is fixed by declaring
macsmc_hwmon_write_f32() as __always_inline for a compile test.

Fixes: 785205fd8139 ("hwmon: Add Apple Silicon SMC hwmon driver")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Closes: https://lore.kernel.org/linux-hwmon/20260119195817.GA1035354@ax162/
Cc: James Calligeros <jcalligeros99@gmail.com>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Neal Gompa <neal@gompa.dev>
Cc: Janne Grunau <j@jannau.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Nathan Chancellor <nathan@kernel.org> # build only
Link: https://lore.kernel.org/r/20260129175112.3751907-2-linux@roeck-us.net
Reviewed-by: James Calligeros <jcalligeros99@gmail.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

+10 -13
+10 -13
drivers/hwmon/macsmc-hwmon.c
··· 228 228 { 229 229 u64 val; 230 230 u32 fval = 0; 231 - int exp = 0, neg; 231 + int exp, neg; 232 232 233 + neg = value < 0; 233 234 val = abs(value); 234 - neg = val != value; 235 235 236 236 if (val) { 237 - int msb = __fls(val) - exp; 237 + exp = __fls(val); 238 238 239 - if (msb > 23) { 240 - val >>= msb - FLT_MANT_BIAS; 241 - exp -= msb - FLT_MANT_BIAS; 242 - } else if (msb < 23) { 243 - val <<= FLT_MANT_BIAS - msb; 244 - exp += msb; 245 - } 239 + if (exp > 23) 240 + val >>= exp - 23; 241 + else 242 + val <<= 23 - exp; 246 243 247 244 fval = FIELD_PREP(FLT_SIGN_MASK, neg) | 248 245 FIELD_PREP(FLT_EXP_MASK, exp + FLT_EXP_BIAS) | 249 - FIELD_PREP(FLT_MANT_MASK, val); 246 + FIELD_PREP(FLT_MANT_MASK, val & FLT_MANT_MASK); 250 247 } 251 248 252 249 return apple_smc_write_u32(smc, key, fval); ··· 660 663 if (!hwmon->volt.sensors) 661 664 return -ENOMEM; 662 665 663 - for_each_child_of_node_with_prefix(hwmon_node, key_node, "volt-") { 664 - sensor = &hwmon->temp.sensors[hwmon->temp.count]; 666 + for_each_child_of_node_with_prefix(hwmon_node, key_node, "voltage-") { 667 + sensor = &hwmon->volt.sensors[hwmon->volt.count]; 665 668 if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) { 666 669 sensor->attrs = HWMON_I_INPUT; 667 670