Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (pmbus) Fix LINEAR16 data format

LINEAR16 data format is unsigned, not signed. Impact is that affected
attributes report negative values in the upper half of the supported
value range.

Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>

+17 -14
+17 -14
drivers/hwmon/pmbus_core.c
··· 359 359 static int pmbus_reg2data_linear(struct pmbus_data *data, 360 360 struct pmbus_sensor *sensor) 361 361 { 362 - s16 exponent, mantissa; 362 + s16 exponent; 363 + s32 mantissa; 363 364 long val; 364 365 365 - if (sensor->class == PSC_VOLTAGE_OUT) { 366 + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ 366 367 exponent = data->exponent; 367 - mantissa = (s16) sensor->data; 368 - } else { 368 + mantissa = (u16) sensor->data; 369 + } else { /* LINEAR11 */ 369 370 exponent = (sensor->data >> 11) & 0x001f; 370 371 mantissa = sensor->data & 0x07ff; 371 372 372 373 if (exponent > 0x0f) 373 374 exponent |= 0xffe0; /* sign extend exponent */ 374 375 if (mantissa > 0x03ff) 375 - mantissa |= 0xf800; /* sign extend mantissa */ 376 + mantissa |= 0xfffff800; /* sign extend mantissa */ 376 377 } 377 378 378 379 val = mantissa; ··· 455 454 static u16 pmbus_data2reg_linear(struct pmbus_data *data, 456 455 enum pmbus_sensor_classes class, long val) 457 456 { 458 - s16 exponent = 0, mantissa = 0; 457 + s16 exponent = 0, mantissa; 459 458 bool negative = false; 460 459 461 460 /* simple case */ 462 461 if (val == 0) 463 462 return 0; 464 463 465 - if (val < 0) { 466 - negative = true; 467 - val = -val; 468 - } 469 - 470 464 if (class == PSC_VOLTAGE_OUT) { 465 + /* LINEAR16 does not support negative voltages */ 466 + if (val < 0) 467 + return 0; 468 + 471 469 /* 472 470 * For a static exponents, we don't have a choice 473 471 * but to adjust the value to it. ··· 476 476 else 477 477 val >>= data->exponent; 478 478 val = DIV_ROUND_CLOSEST(val, 1000); 479 - if (val > 0x7fff) 480 - val = 0x7fff; 481 - return negative ? -val : val; 479 + return val & 0xffff; 480 + } 481 + 482 + if (val < 0) { 483 + negative = true; 484 + val = -val; 482 485 } 483 486 484 487 /* Power is in uW. Convert to mW before converting. */