Skip to content

Commit c882e8c

Browse files
vjardingregkh
authored andcommitted
i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)
[ Upstream commit cb2fc37 ] SMBus 3.1 6.5.7 allows a Block Read byte count of 0, but the atomic (polling) path rejects it as -EPROTO. Worse, it returns without a NACK+STOP: the next receive cycle has already started, so the target keeps holding SDA and the bus stays stuck until a power cycle for this i2c controller. Reading I2DR to obtain the count likewise arms the next byte on the count > I2C_SMBUS_BLOCK_MAX path, which also returned -EPROTO directly and left the bus held. Handle both: NACK the in-flight dummy byte (TXAK) and extend msgs->len so the existing last-byte handling emits STOP; the dummy byte is discarded. A count of 0 is a valid empty block read; a count above I2C_SMBUS_BLOCK_MAX is still reported as -EPROTO, but only after the bus has been released. The interrupt-driven path has the same flaw from a later commit and is fixed separately, as it carries a different Fixes: tag and stable range. Fixes: 8e8782c ("i2c: imx: add SMBus block read support") Signed-off-by: Vincent Jardin <vjardin@free.fr> Cc: <stable@vger.kernel.org> # v3.16+ Acked-by: Oleksij Rempel <o.rempel@pengutronix.de> Acked-by: Carlos Song <carlos.song@nxp.com> Reviewed-by: Stefan Eichenberger <eichest@gmail.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://lore.kernel.org/r/20260713-for-upstream-i2c-lx2160-fix-v1-v3-1-073ac9e103a5@free.fr Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e569563 commit c882e8c

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

drivers/i2c/busses/i2c-imx.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
11801180
int i, result;
11811181
unsigned int temp;
11821182
int block_data = msgs->flags & I2C_M_RECV_LEN;
1183+
int block_err = 0;
11831184

11841185
result = i2c_imx_prepare_read(i2c_imx, msgs, atomic, false);
11851186
if (result)
@@ -1201,8 +1202,20 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
12011202
*/
12021203
if ((!i) && block_data) {
12031204
len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
1204-
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
1205-
return -EPROTO;
1205+
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
1206+
/*
1207+
* SMBus 3.1 6.5.7: support count byte of 0.
1208+
* I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
1209+
*/
1210+
if (len > I2C_SMBUS_BLOCK_MAX)
1211+
block_err = -EPROTO;
1212+
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
1213+
temp |= I2CR_TXAK;
1214+
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
1215+
msgs->buf[0] = 0;
1216+
msgs->len = 2;
1217+
continue;
1218+
}
12061219
dev_dbg(&i2c_imx->adapter.dev,
12071220
"<%s> read length: 0x%X\n",
12081221
__func__, len);
@@ -1250,7 +1263,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
12501263
"<%s> read byte: B%d=0x%X\n",
12511264
__func__, i, msgs->buf[i]);
12521265
}
1253-
return 0;
1266+
return block_err;
12541267
}
12551268

12561269
static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,

0 commit comments

Comments
 (0)