diff options
author | Adam Wujek <dev_public@wujek.eu> | 2022-05-19 23:34:01 +0000 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2022-05-22 11:32:32 -0700 |
commit | d1baf7a3a3177d46a7149858beddb88a9eca7a54 (patch) | |
tree | 9b3697b18ebef8f731b52395470340acd185f896 /drivers/hwmon/pmbus | |
parent | 9baabde04de64137e86b39112c6259f3da512bd6 (diff) | |
download | linux-stable-d1baf7a3a3177d46a7149858beddb88a9eca7a54.tar.gz linux-stable-d1baf7a3a3177d46a7149858beddb88a9eca7a54.tar.bz2 linux-stable-d1baf7a3a3177d46a7149858beddb88a9eca7a54.zip |
hwmon: (pmbus) Check PEC support before reading other registers
Make sure that the support of PEC is determined before the read of other
registers. Otherwise the validation of PEC can trigger an error on the read
of STATUS_BYTE or STATUS_WORD registers.
The problematic scenario is the following. A device with enabled PEC
support is up and running and a kernel driver is loaded.
Then the driver is unloaded (or device unbound), the HW device
is reconfigured externally (e.g. by i2cset) to advertise itself as not
supporting PEC. Without the move of the code, at the second load of
the driver (or bind) the STATUS_BYTE or STATUS_WORD register is always
read with PEC enabled, which is likely to cause a read error resulting
with fail of a driver load (or bind).
Signed-off-by: Adam Wujek <dev_public@wujek.eu>
Link: https://lore.kernel.org/r/20220519233334.438621-1-dev_public@wujek.eu
Fixes: 75d2b2b06bd84 ("hwmon: (pmbus) disable PEC if not enabled")
Fixes: 4e5418f787ec5 ("hwmon: (pmbus_core) Check adapter PEC support")
[groeck: Added Fixes: tags, dropped continuation line]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index cf0e77383898..02912022853d 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -2395,6 +2395,21 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, int page, ret; /* + * Figure out if PEC is enabled before accessing any other register. + * Make sure PEC is disabled, will be enabled later if needed. + */ + client->flags &= ~I2C_CLIENT_PEC; + + /* Enable PEC if the controller and bus supports it */ + if (!(data->flags & PMBUS_NO_CAPABILITY)) { + ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY); + if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK)) { + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC)) + client->flags |= I2C_CLIENT_PEC; + } + } + + /* * Some PMBus chips don't support PMBUS_STATUS_WORD, so try * to use PMBUS_STATUS_BYTE instead if that is the case. * Bail out if both registers are not supported. @@ -2412,19 +2427,6 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, data->has_status_word = true; } - /* Make sure PEC is disabled, will be enabled later if needed */ - client->flags &= ~I2C_CLIENT_PEC; - - /* Enable PEC if the controller and bus supports it */ - if (!(data->flags & PMBUS_NO_CAPABILITY)) { - ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY); - if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK)) { - if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC)) { - client->flags |= I2C_CLIENT_PEC; - } - } - } - /* * Check if the chip is write protected. If it is, we can not clear * faults, and we should not try it. Also, in that case, writes into |