[PATCH linux dev-5.8 3/3] pmbus: (core) Add a one-shot retry in pmbus_set_page()
Andrew Jeffery
andrew at aj.id.au
Thu Aug 27 23:30:02 AEST 2020
>From extensive testing and tracing it was discovered that the MAX31785
occasionally fails to switch pages despite ACK'ing the PAGE PMBus data
write. I suspect this behaviour had been seen on other devices as well,
as pmbus_set_page() already read-back the freshly set value and errored
out if it wasn't what we requested.
In the case of the MAX31785 it was shown that a one-shot retry was
enough to get the PAGE write to stick if the inital command failed. To
improve robustness, only error out if the one-shot retry also fails to
stick.
Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
drivers/hwmon/pmbus/pmbus_core.c | 33 ++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 702c25010369..7d0aac59af31 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -158,25 +158,34 @@ int pmbus_set_page(struct i2c_client *client, int page, int phase)
if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL) &&
data->info->pages > 1 && page != data->currpage) {
+ int i;
+
dev_dbg(&client->dev, "Want page %u, %u cached\n", page,
data->currpage);
- rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
- if (rv < 0) {
+ for (i = 0; i < 2; i++) {
rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE,
page);
- dev_dbg(&client->dev,
- "Failed to set page %u, performed one-shot retry %s: %d\n",
- page, rv ? "and failed" : "with success", rv);
+
+ if (rv)
+ continue;
+
+ rv = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
if (rv < 0)
- return rv;
+ continue;
+
+ /* Success, exit loop */
+ if (rv == page)
+ break;
+
+ rv = i2c_smbus_read_byte_data(client, PMBUS_STATUS_CML);
+ if (rv < 0)
+ continue;
+
+ if (rv & PB_CML_FAULT_INVALID_DATA)
+ return -EIO;
}
-
- rv = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
- if (rv < 0)
- return rv;
-
- if (rv != page)
+ if (i == 2)
return -EIO;
}
data->currpage = page;
--
2.25.1
More information about the openbmc
mailing list