Re: [PATCH RESEND] hwmon: (corsair-psu) Fix linear11 calculation

Guenter Roeck <[email protected]> Mon, 3 Aug 2026 19:58:20 -0700
Newsgroups org.kernel.vger.linux-hwmon
Message-ID <[email protected]>
On 8/3/26 17:15, Ali Ahmet Memis wrote:
> On Mon,  3 Aug 2026 16:21:55 -0700 Guenter Roeck wrote:
>> +	if (exp >= 0)
>> +		result *= (int)(1UL << exp);
>> +	else
>> +		result /= (int)(1UL << -exp);
> 
> This breaks the build on 32 bit. result is s64 and the divisor is only known
> at runtime, so the compiler emits a libgcc call instead of a shift, and
> __divdi3 is only provided by sparc and parisc. SENSORS_CORSAIR_PSU just
> depends on HID, so i386 and 32 bit arm are reachable.
> 
> On this patch applied to 2d2338c93da7:
> 
>    $ make ARCH=i386 defconfig
>    $ ./scripts/config --set-val CONFIG_SENSORS_CORSAIR_PSU y
>    $ make ARCH=i386 olddefconfig
>    $ make ARCH=i386 vmlinux
>    [...]
>      LD      .tmp_vmlinux1
>    ld: drivers/hwmon/corsair-psu.o: in function `corsairpsu_get_value':
>    corsair-psu.c:(.text+0xa0b): undefined reference to `__divdi3'
>    ld: corsair-psu.c:(.text+0xa63): undefined reference to `__divdi3'
>    ld: corsair-psu.c:(.text+0xa83): undefined reference to `__divdi3'
>    ld: corsair-psu.c:(.text+0xaa3): undefined reference to `__divdi3'
>    make[2]: *** [scripts/Makefile.vmlinux:72: vmlinux.unstripped] Error 1
> 
> Only the divide is a problem, the multiply builds fine. div_s64() would do
> it, or keeping a shift on the negative branch, since the divisor is a power
> of two anyway.
> 
> The mantissa fix itself looks right to me. ((s16)((val & 0x7ff) << 5)) >> 5
> puts bit 10 of the mantissa into the sign bit of the s16 before the
> arithmetic shift brings it back, which is what the old order failed to do.
> 
> One small thing on the changelog: it says right shifting negative values is
> implementation defined and that multiply and divide are used to avoid that,
> but exp and mant are still computed with >> on values that can be negative.
> That is the normal sign extension idiom and fine in practice, it just reads
> as if those had been converted too.

Good point. Supposedly is implementation defined, but even sign_extend32()
uses it, so I'll just undo that part.

Thanks,
Guenter