aboutsummaryrefslogtreecommitdiff
path: root/hw/i2c
diff options
context:
space:
mode:
authorTitus Rwantare <titusr@google.com>2023-10-23 23:46:47 +0000
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-11-07 13:08:49 +0100
commitff0511282d406150984de1aaaaad451da8ad3a1c (patch)
tree1ce565441b2eb830629affd790c16229fae9197c /hw/i2c
parent84db503e7c260ace0cf7267379955bbae77e85a4 (diff)
hw/i2c: pmbus: reset page register for out of range reads
The linux pmbus driver scans all possible pages and does not reset the current page after the scan, making all future page reads fail as out of range on devices with a single page. This change resets out of range pages immediately on write. Also added a qtest for simultaneous writes to all pages. Reviewed-by: Hao Wu <wuhaotsh@google.com> Signed-off-by: Titus Rwantare <titusr@google.com> Message-ID: <20231023-staging-pmbus-v3-v4-8-07a8cb7cd20a@google.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'hw/i2c')
-rw-r--r--hw/i2c/pmbus_device.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c
index 481e158380..1b978e588f 100644
--- a/hw/i2c/pmbus_device.c
+++ b/hw/i2c/pmbus_device.c
@@ -1255,6 +1255,15 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_t *buf, uint8_t len)
if (pmdev->code == PMBUS_PAGE) {
pmdev->page = pmbus_receive8(pmdev);
+
+ if (pmdev->page > pmdev->num_pages - 1 && pmdev->page != PB_ALL_PAGES) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: page %u is out of range\n",
+ __func__, pmdev->page);
+ pmdev->page = 0; /* undefined behaviour - reset to page 0 */
+ pmbus_cml_error(pmdev);
+ return PMBUS_ERR_BYTE;
+ }
return 0;
}
@@ -1268,15 +1277,6 @@ static int pmbus_write_data(SMBusDevice *smd, uint8_t *buf, uint8_t len)
return 0;
}
- if (pmdev->page > pmdev->num_pages - 1) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: page %u is out of range\n",
- __func__, pmdev->page);
- pmdev->page = 0; /* undefined behaviour - reset to page 0 */
- pmbus_cml_error(pmdev);
- return PMBUS_ERR_BYTE;
- }
-
index = pmdev->page;
switch (pmdev->code) {