Re: [PATCH] hwmon: (lm70) Fix rounding of negative temperatures

From: David Laight

Date: Sun Sep 27 2026 - 02:31:40 EST


On Fri, 25 Sep 2026 20:03:06 +0200
Christian Lamparter <chunkeey@xxxxxxxxx> wrote:

> Hi,
>
> On 9/24/26 10:53 PM, Ridham Khurana wrote:
> > temp1_input_show() drops the low bits of the temperature register by
> > dividing the raw value (raw / 32 on the LM70). These bits are not part
> > of the temperature: the LM70, LM71, LM74 and TMP122/TMP124 always
> > return some of them as 1, and the TMP125 fills them with copies of the
> > temperature LSB. Division rounds toward zero, so a negative temperature
> > with any of these bits set is reported one LSB too high.
> >
> > For example, the TMP122 returns 0xffff for -0.0625 degrees C, which the
> > driver reports as 0. The LM70 returns 0xf39f for -25 degrees C, which
> > the driver reports as -24750.
> >
> > Use an arithmetic right shift instead, which drops the low bits and
> > rounds down. tmp421 had a similar problem with negative values, fixed
> > by commit 724e8af85854 ("hwmon: (tmp421) fix rounding for negative
> > values").
>
> For the TMP125 yes:
>
> Reviewed-by: Christian Lamparter <chunkeey@xxxxxxxxx>
>
>
> > Fixes: e1a8e913f97e ("[PATCH] lm70: New hardware monitoring driver")
> > Fixes: a86e94dc946d ("hwmon: (lm70) Add support for LM71 and LM74")
> > Fixes: cd929672a9ef ("hwmon: (lm70) Add ti,tmp125 support")
> > Signed-off-by: Ridham Khurana <khurana.ridham222@xxxxxxxxx>
> > ----
> I wrote a little test program by hand (see below) and ran it on x64.
> No idea if different archs behave differently or if
> a clever unsafe math optimizing compiler flag will
> convert the "/ 32" to a " >> 5" but I doubt that...

A compiler will convert an unsigned divide to a shift, but can't
do so for signed divides.

But you'll also get flagged because C doesn't define right shifts
for negative values.
I think they are actually 'undefined behaviour' (UB) if clang detects
that your code is UB it silently just stops generating object code.
(int)((val + 0x8000u) / 16u - 0x8000)
might safely generate the correct value.

David