mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 19:31:42 -04:00
hwmon: (pmbus/mp2869) Check pmbus_read_byte_data() before using its return value
In mp2869_read_byte_data() and mp2869_read_word_data(), the return value
of pmbus_read_byte_data() for PMBUS_STATUS_MFR_SPECIFIC is used directly
inside FIELD_GET() macro arguments without error checking. If the I2C
transaction fails, a negative error code is passed to FIELD_GET() and
FIELD_PREP(), silently corrupting the status register bits being
constructed.
Extract the nested pmbus_read_byte_data() calls into a separate variable
and check for errors before use. This also eliminates a redundant duplicate
read of the same register in the PMBUS_STATUS_TEMPERATURE case.
Fixes: a3a2923aaf ("hwmon: add MP2869,MP29608,MP29612 and MP29816 series driver")
Cc: stable@vger.kernel.org
Signed-off-by: Sanman Pradhan <psanman@juniper.net>
Link: https://lore.kernel.org/r/20260317173308.382545-4-sanman.pradhan@hpe.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
committed by
Guenter Roeck
parent
19d4b9c8a1
commit
c6f45ed26b
@@ -165,7 +165,7 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct mp2869_data *data = to_mp2869_data(info);
|
||||
int ret;
|
||||
int ret, mfr;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VOUT_MODE:
|
||||
@@ -188,11 +188,14 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mfr = pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (mfr < 0)
|
||||
return mfr;
|
||||
|
||||
ret = (ret & ~GENMASK(2, 2)) |
|
||||
FIELD_PREP(GENMASK(2, 2),
|
||||
FIELD_GET(GENMASK(1, 1),
|
||||
pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC)));
|
||||
FIELD_GET(GENMASK(1, 1), mfr));
|
||||
break;
|
||||
case PMBUS_STATUS_TEMPERATURE:
|
||||
/*
|
||||
@@ -207,15 +210,16 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mfr = pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (mfr < 0)
|
||||
return mfr;
|
||||
|
||||
ret = (ret & ~GENMASK(7, 6)) |
|
||||
FIELD_PREP(GENMASK(6, 6),
|
||||
FIELD_GET(GENMASK(1, 1),
|
||||
pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC))) |
|
||||
FIELD_GET(GENMASK(1, 1), mfr)) |
|
||||
FIELD_PREP(GENMASK(7, 7),
|
||||
FIELD_GET(GENMASK(1, 1),
|
||||
pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC)));
|
||||
FIELD_GET(GENMASK(1, 1), mfr));
|
||||
break;
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
@@ -230,7 +234,7 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase,
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct mp2869_data *data = to_mp2869_data(info);
|
||||
int ret;
|
||||
int ret, mfr;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_STATUS_WORD:
|
||||
@@ -246,11 +250,14 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mfr = pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (mfr < 0)
|
||||
return mfr;
|
||||
|
||||
ret = (ret & ~GENMASK(2, 2)) |
|
||||
FIELD_PREP(GENMASK(2, 2),
|
||||
FIELD_GET(GENMASK(1, 1),
|
||||
pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC)));
|
||||
FIELD_GET(GENMASK(1, 1), mfr));
|
||||
break;
|
||||
case PMBUS_READ_VIN:
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user