Skip to content

Commit

Permalink
w1: w1_therm: Fix conversion result for negative temperatures
Browse files Browse the repository at this point in the history
commit 2f6055c upstream.

DS18B20 device driver returns an incorrect value for negative temperatures
due to a missing sign-extension in w1_DS18B20_convert_temp().

Fix by using s16 temperature value when converting to int.

See: raspberrypi/linux#4124

Fixes: 9ace0b4 (w1: w1_therm: Add support for GXCAS GX20MH01 device.)
Cc: stable <stable@vger.kernel.org>
Reported-by: Paweł Marciniak <sunwire@gmail.com>
Signed-off-by: Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
Link: https://lore.kernel.org/r/20210121093021.224764-1-ivan.zaentsev@wirenboard.ru
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Fang Yafen <yafen@iscas.ac.cn>
  • Loading branch information
Ivan Zaentsev authored and Fang Yafen committed Feb 26, 2021
1 parent c69a7e7 commit 6aca0d4
Showing 1 changed file with 9 additions and 13 deletions.
22 changes: 9 additions & 13 deletions drivers/w1/slaves/w1_therm.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,28 +667,24 @@ static inline int w1_DS18B20_get_resolution(struct w1_slave *sl)
*/
static inline int w1_DS18B20_convert_temp(u8 rom[9])
{
int t;
u32 bv;
u16 bv;
s16 t;

/* Signed 16-bit value to unsigned, cpu order */
bv = le16_to_cpup((__le16 *)rom);

/* Config register bit R2 = 1 - GX20MH01 in 13 or 14 bit resolution mode */
if (rom[4] & 0x80) {
/* Signed 16-bit value to unsigned, cpu order */
bv = le16_to_cpup((__le16 *)rom);

/* Insert two temperature bits from config register */
/* Avoid arithmetic shift of signed value */
bv = (bv << 2) | (rom[4] & 3);

t = (int) sign_extend32(bv, 17); /* Degrees, lowest bit is 2^-6 */
return (t*1000)/64; /* Millidegrees */
t = (s16) bv; /* Degrees, lowest bit is 2^-6 */
return (int)t * 1000 / 64; /* Sign-extend to int; millidegrees */
}

t = (int)le16_to_cpup((__le16 *)rom);
return t*1000/16;
t = (s16)bv; /* Degrees, lowest bit is 2^-4 */
return (int)t * 1000 / 16; /* Sign-extend to int; millidegrees */
}



/**
* w1_DS18S20_convert_temp() - temperature computation for DS18S20
* @rom: data read from device RAM (8 data bytes + 1 CRC byte)
Expand Down

0 comments on commit 6aca0d4

Please sign in to comment.