Re: [PATCH] hwmon: (max6621) fix negative temperature offset and crit readings

Guenter Roeck <[email protected]>
Newsgroups org.kernel.vger.linux-hwmon,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 8/8/26 08:54, Nguyễn Công wrote:
> On Sat, Aug 8, 2026 at 9:48 PM Guenter Roeck <[email protected]> wrote:
>>
>> On 8/8/26 01:37, Cong Nguyen wrote:
>>> max6621_read() reads the temperature input, offset and critical alert
>>> registers into a u32 and assigns them to the output without sign
>>> extension. The device reports these values in two's complement (the
>>> driver comment and the write path, which clamps to
>>> MAX6621_TEMP_INPUT_MIN == -127000 and encodes negatives, both rely on
>>> this), so negative values are misreported as large positive numbers:
>>>
>>>     - temp_offset: *val = (regval >> MAX6621_REG_TEMP_SHIFT) * 1000, an
>>>       unsigned shift, so e.g. a -10 degrees C offset (register 0xfd80)
>>>       reads back as ~+1014000 millidegrees.
>>>     - temp_crit: *val = regval * 1000, so a negative critical threshold
>>>       reads back as a large positive value.
>>>     - temp_input used an s8 intermediate, which is correct for the
>>>       -127..127 range but reports the documented +128 degrees C maximum as
>>>       -128 degrees C.
>>>
>>
>> This problem does not exist. The AI is hallucinating a bit. There is no mention
>> of +128 degrees C in the datasheet.
>>
>> The problem here is that MAX6621_TEMP_INPUT_MIN (-127) and MAX6621_TEMP_INPUT_MAX (128)
>> are wrong. That should be -128 and (+)127. I guess the AI doesn't see that.
>>
>>> The registers are 16-bit (the driver's own PECI error codes occupy
>>> 0x8000-0x80ff), so sign-extend from bit 15 before scaling. This fixes
>>> all three reads and drops the now-unused s8 intermediate.
>>>
>>
>> The PECI error code reference is just confusing AI slop and completely irrelevant
>> for the patch.
>>
>>> Fixes: 92b64580f14b ("hwmon: (max6621) Add support for Maxim MAX6621 temperature sensor")
>>> Cc: [email protected]
>>> Assisted-by: Claude:claude-opus-4
>>> Signed-off-by: Cong Nguyen <[email protected]>
>>> ---
>>>    drivers/hwmon/max6621.c | 11 +++++------
>>>    1 file changed, 5 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c
>>> index a7066f3a0bb4..03ac3eb5a594 100644
>>> --- a/drivers/hwmon/max6621.c
>>> +++ b/drivers/hwmon/max6621.c
>>> @@ -204,7 +204,6 @@ max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
>>>        struct max6621_data *data = dev_get_drvdata(dev);
>>>        u32 regval;
>>>        int reg;
>>> -     s8 temp;
>>>        int ret;
>>>
>>>        switch (type) {
>>> @@ -225,8 +224,8 @@ max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
>>>                         * The temperature is given in two's complement and 8
>>>                         * bits is used for the register conversion.
>>>                         */
>>> -                     temp = (regval >> MAX6621_REG_TEMP_SHIFT);
>>> -                     *val = temp * 1000L;
>>> +                     *val = (sign_extend32(regval, 15) >>
>>> +                             MAX6621_REG_TEMP_SHIFT) * 1000L;
>>
>>                          *val = ((s16)regval >> MAX6621_REG_TEMP_SHIFT) * 1000L;
>>
>> However, as mentioned above, this is not a problem in the first place
>> but AI not understanding the code and the real problem..
>>
>> Guenter
>>
>>>
>>>                        break;
>>>                case hwmon_temp_offset:
>>> @@ -239,8 +238,8 @@ max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
>>>                        if (ret)
>>>                                return ret;
>>>
>>> -                     *val = (regval >> MAX6621_REG_TEMP_SHIFT) *
>>> -                            1000L;
>>> +                     *val = (sign_extend32(regval, 15) >>
>>> +                             MAX6621_REG_TEMP_SHIFT) * 1000L;
>>>
>>>                        break;
>>>                case hwmon_temp_crit:
>>> @@ -254,7 +253,7 @@ max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
>>>                        if (ret)
>>>                                return ret;
>>>
>>> -                     *val = regval * 1000L;
>>> +                     *val = sign_extend32(regval, 15) * 1000L;
>>>
>>>                        break;
>>>                case hwmon_temp_crit_alarm:
>>
> 
> You're right - temp_input is fine (the s8 already sign-extends -128..127),
> and the +128/PECI reasoning was wrong. Sorry for the noise.
> 
> Agreed the real bug is the clamp range: MAX6621_TEMP_INPUT_MIN/MAX should be
> -128000/127000. Would you like me to send a v2 for that, or would you rather
> just fix it directly?
> 
> If a v2 is useful: temp_offset/temp_crit also don't use the s8 - they scale a
> raw u32 - so a negative offset round-trips wrong (write -10 degC -> mc2reg
> 0xfd80 -> reads back 1014000). I can fold a (s16) fix for those in too, if you
> agree it's a real issue.
> 
It should be two patches: One fixing the range, the other fixing the negative
temperature values in _offset and _crit.

Thanks,
Guenter
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.