[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 56/60] hw/i2c: pmbus: reset page register for out of range reads
From: |
Philippe Mathieu-Daudé |
Subject: |
[PULL 56/60] hw/i2c: pmbus: reset page register for out of range reads |
Date: |
Mon, 6 Nov 2023 12:03:28 +0100 |
From: Titus Rwantare <titusr@google.com>
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>
---
hw/i2c/pmbus_device.c | 18 +++++++++---------
tests/qtest/max34451-test.c | 24 ++++++++++++++++++++++++
2 files changed, 33 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) {
diff --git a/tests/qtest/max34451-test.c b/tests/qtest/max34451-test.c
index 0c98d0764c..dbf6ddc829 100644
--- a/tests/qtest/max34451-test.c
+++ b/tests/qtest/max34451-test.c
@@ -18,6 +18,7 @@
#define TEST_ID "max34451-test"
#define TEST_ADDR (0x4e)
+#define MAX34451_MFR_MODE 0xD1
#define MAX34451_MFR_VOUT_PEAK 0xD4
#define MAX34451_MFR_IOUT_PEAK 0xD5
#define MAX34451_MFR_TEMPERATURE_PEAK 0xD6
@@ -315,6 +316,28 @@ static void test_ot_faults(void *obj, void *data,
QGuestAllocator *alloc)
}
}
+#define RAND_ON_OFF_CONFIG 0x12
+#define RAND_MFR_MODE 0x3456
+
+/* test writes to all pages */
+static void test_all_pages(void *obj, void *data, QGuestAllocator *alloc)
+{
+ uint16_t i2c_value;
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
+
+ i2c_set8(i2cdev, PMBUS_PAGE, PB_ALL_PAGES);
+ i2c_set8(i2cdev, PMBUS_ON_OFF_CONFIG, RAND_ON_OFF_CONFIG);
+ max34451_i2c_set16(i2cdev, MAX34451_MFR_MODE, RAND_MFR_MODE);
+
+ for (int i = 0; i < MAX34451_NUM_TEMP_DEVICES + MAX34451_NUM_PWR_DEVICES;
+ i++) {
+ i2c_value = i2c_get8(i2cdev, PMBUS_ON_OFF_CONFIG);
+ g_assert_cmphex(i2c_value, ==, RAND_ON_OFF_CONFIG);
+ i2c_value = max34451_i2c_get16(i2cdev, MAX34451_MFR_MODE);
+ g_assert_cmphex(i2c_value, ==, RAND_MFR_MODE);
+ }
+}
+
static void max34451_register_nodes(void)
{
QOSGraphEdgeOptions opts = {
@@ -332,5 +355,6 @@ static void max34451_register_nodes(void)
qos_add_test("test_ro_regs", "max34451", test_ro_regs, NULL);
qos_add_test("test_ov_faults", "max34451", test_ov_faults, NULL);
qos_add_test("test_ot_faults", "max34451", test_ot_faults, NULL);
+ qos_add_test("test_all_pages", "max34451", test_all_pages, NULL);
}
libqos_init(max34451_register_nodes);
--
2.41.0
- [PULL 47/60] hw/ide: reset: cancel async DMA operation before resetting state, (continued)
- [PULL 47/60] hw/ide: reset: cancel async DMA operation before resetting state, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 49/60] hw/i2c: pmbus add support for block receive, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 48/60] tests/qtest: ahci-test: add test exposing reset issue with pending callback, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 50/60] hw/i2c: pmbus: add vout mode bitfields, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 51/60] hw/i2c: pmbus: add fan support, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 52/60] hw/i2c: pmbus: add VCAP register, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 53/60] hw/sensor: add ADM1266 device model, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 54/60] tests/qtest: add tests for ADM1266, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 55/60] hw/i2c: pmbus: immediately clear faults on request, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 58/60] MAINTAINERS: Add the CAN documentation file to the CAN section, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 56/60] hw/i2c: pmbus: reset page register for out of range reads,
Philippe Mathieu-Daudé <=
- [PULL 60/60] ui/sdl2: use correct key names in win title on mac, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 57/60] MAINTAINERS: Add include/hw/timer/tmu012.h to the SH4 R2D section, Philippe Mathieu-Daudé, 2023/11/06
- [PULL 59/60] MAINTAINERS: update libvirt devel mailing list address, Philippe Mathieu-Daudé, 2023/11/06
- Re: [PULL 00/60] Misc HW/UI patches for 2023-11-06, Stefan Hajnoczi, 2023/11/06