[PATCH 3/8] hw/i2c: smbus: increase MAX_DATA_LEN
Titus Rwantare <[email protected]> Wed, 29 Jul 2026 23:13:18 +0000
| Newsgroups | org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
The 32 byte payload was raised to 255 for block reads in the SMBus 3.0 specification. SMBus does not provide a way for devices to declare which version of the spec they are designed to so we must allow newer devices to return as much data as they allow. vsmstate_smbus_extended_data is added to avoid breaking migration. Specification: https://smbus.org/specs/SMBus_3_3_20240512.pdf > 6.5.7 Block Write/Read The Block Write begins with a slave address and a write condition. After th= e command code the host issues a byte count which describes how many more b= ytes will follow in the message. If a slave has 20 bytes to send, the byte = count field will have the value 20 (14h), followed by the 20 bytes of data.= The byte count does not include the PEC byte. The byte count may be 0. A B= lock Read or Block Write is allowed to transfer a maximum of 255 data bytes= . Signed-off-by: Titus Rwantare <[email protected]> --- hw/i2c/smbus_slave.c | 27 ++++++++++++++++++++++++++- include/hw/i2c/smbus_slave.h | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/hw/i2c/smbus_slave.c b/hw/i2c/smbus_slave.c index cfb61c879e..5dd2c38af7 100644 --- a/hw/i2c/smbus_slave.c +++ b/hw/i2c/smbus_slave.c @@ -215,6 +215,26 @@ bool smbus_vmstate_needed(SMBusDevice *dev) return dev->mode !=3D SMBUS_IDLE; } =20 +#define SMBUS_DATA_MAX_LEN_OLD 34 +static bool smbus_extended_needed(void *opaque) +{ + SMBusDevice *dev =3D opaque; + return dev->data_len > SMBUS_DATA_MAX_LEN_OLD; +} + +static const VMStateDescription vmstate_smbus_extended_data =3D { + .name =3D TYPE_SMBUS_DEVICE"/extended", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D smbus_extended_needed, + .fields =3D (const VMStateField[]) { + /* separately save [34..257) */ + VMSTATE_UINT8_SUB_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN_= OLD, + SMBUS_DATA_MAX_LEN - SMBUS_DATA_MAX_LEN_OLD), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_smbus_device =3D { .name =3D TYPE_SMBUS_DEVICE, .version_id =3D 1, @@ -223,8 +243,13 @@ const VMStateDescription vmstate_smbus_device =3D { VMSTATE_I2C_SLAVE(i2c, SMBusDevice), VMSTATE_INT32(mode, SMBusDevice), VMSTATE_INT32(data_len, SMBusDevice), - VMSTATE_UINT8_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN), + VMSTATE_UINT8_SUB_ARRAY(data_buf, SMBusDevice, 0, + SMBUS_DATA_MAX_LEN_OLD), VMSTATE_END_OF_LIST() + }, + .subsections =3D (const VMStateDescription * const[]) { + &vmstate_smbus_extended_data, + NULL } }; =20 diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index 86bfe0a79e..59522ff1b1 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -64,7 +64,7 @@ struct SMBusDeviceClass { uint8_t (*receive_byte)(SMBusDevice *dev); }; =20 -#define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */ +#define SMBUS_DATA_MAX_LEN 257 /* command + len + 255 bytes of data. */ =20 struct SMBusDevice { /* The SMBus protocol is implemented on top of I2C. */ --=20 2.55.0.508.g3f0d502094-goog