summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Zaentsev <ivan.zaentsev@wirenboard.ru>2021-01-21 12:30:21 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-04 13:37:18 +0300
commit1ad8f7fc4aa73db62886a62a3396bec912fe4533 (patch)
tree082781fff16b0f12442c2baa6be93ae12c36ac0f
parented5d02f0a77849c520e78899ca23c249966f49b9 (diff)
downloadlinux-1ad8f7fc4aa73db62886a62a3396bec912fe4533.tar.xz
w1: w1_therm: Fix conversion result for negative temperatures
commit 2f6055c26f1913763eabc66c7c27d0693561e966 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. Fixes: 9ace0b4dab1c (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>
-rw-r--r--drivers/w1/slaves/w1_therm.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index cddf60b7309c..974d02bb3a45 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -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)