From nobody Sat Jul 25 20:54:15 2026 Received: from smtp1-g21.free.fr (smtp1-g21.free.fr [212.27.42.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2B15344D9D; Mon, 13 Jul 2026 18:12:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.42.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783966371; cv=none; b=d8PQdgLNlMI9q+RLjUBPsk12i3kfq/acIULRgqN4gfIJB8DCckJ33FHpVH6VBhRAgO3NtIJ4W63MmaEhbpRhy5EceaVaCdFM3hfU9M4ETosxVDckpMXIjr66v6fg//GtIlLE6KoaAssCBJ1ORTqAS2LSOWBQqAMwQRJ2AukFAXI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783966371; c=relaxed/simple; bh=MB93t3nfvRdSDolU+OMtP3YuXMmW9lVD3yUEkEyoz4E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PguY0o7OUbZ3WVhN+3kGgmhWwvIFg8mFXwe8QdFLx2whyi4kxuHQKPulO9TVU+V2ibALDg3aT/+3AZhX+VK+Ffw2/V9jKnHP9ODcj7QAos8u67a7ld8CaTg9MkaUYCmEm8nKvs/T0/zh99pT0/GkQnd7WoxrDTQ4ZFc/Jqdgbes= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=free.fr; spf=pass smtp.mailfrom=free.fr; dkim=pass (2048-bit key) header.d=free.fr header.i=@free.fr header.b=OMZSLA/+; arc=none smtp.client-ip=212.27.42.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=free.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=free.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=free.fr header.i=@free.fr header.b="OMZSLA/+" Received: from [127.0.1.1] (unknown [91.160.0.144]) (Authenticated sender: vjardin@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 67DAFB005AC; Mon, 13 Jul 2026 20:12:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=free.fr; s=smtp-20201208; t=1783966366; bh=MB93t3nfvRdSDolU+OMtP3YuXMmW9lVD3yUEkEyoz4E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OMZSLA/+hz/KDAZ/BHUjwQDa+chahuXZN/6mgR4ZOBZ7SMCIMuJNb/wx0E7axbUlF Cx+XhNxgMvLAI7v9txj6L89fCcNcphBC91+OUXhw5jMmBOnIHegDVe/q3nBmU15WCg C+NhvZAYQpL6BKLSFfBSCzcMX+CSew9bZYxW7udK7/0XY66iL1qnZyM71D58K/7cx1 65v/XY8Qyz5rKjQ27aC7c3qmewIgue8IPnLWXzgoVBDQZVn05ds6G+yse9uWVtGRd2 SfWW1xVgZs8PgX6X94mntoTjBMccXLCtjnU02cxUAe3ErGYC7IMB32XR+R5n6rw46v t5FD12NGs2NnQ== From: Vincent Jardin Date: Mon, 13 Jul 2026 20:11:59 +0200 Subject: [PATCH v3 1/2] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-1-073ac9e103a5@free.fr> References: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-0-073ac9e103a5@free.fr> In-Reply-To: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-0-073ac9e103a5@free.fr> To: Oleksij Rempel , Pengutronix Kernel Team , Andi Shyti , Frank Li , Sascha Hauer , Fabio Estevam , Wolfram Sang , Kaushal Butala , Shawn Guo , Stefan Eichenberger Cc: linux-i2c@vger.kernel.org, imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Vincent Jardin , stable@vger.kernel.org, Carlos Song , Stefan Eichenberger X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783966324; l=2882; i=vjardin@free.fr; s=20260525; h=from:subject:message-id; bh=MB93t3nfvRdSDolU+OMtP3YuXMmW9lVD3yUEkEyoz4E=; b=EAfrG/l4yjYiRBr25rzQTMFXUHFvyfy+O1ND7nv0EOzDLBLyPO6dtiIZ9uQ03Tp6SxZiheqBz JrUTvnQi4hKBqZxQEdPdvJE7v9jDM9LJ990XiZtdDvVT/z/tWccsFmi X-Developer-Key: i=vjardin@free.fr; a=ed25519; pk=hppgLeFpGpKOi7LNwGEZ4jOYofJCoGd4Jf1ltAabiLw= 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: 8e8782c71595 ("i2c: imx: add SMBus block read support") Cc: stable@vger.kernel.org # v3.16+ Acked-by: Oleksij Rempel Acked-by: Carlos Song Reviewed-by: Stefan Eichenberger Signed-off-by: Vincent Jardin --- drivers/i2c/busses/i2c-imx.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 28313d0fad37..cfd1e63359e7 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1415,6 +1415,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct = *i2c_imx, int i, result; unsigned int temp; int block_data =3D msgs->flags & I2C_M_RECV_LEN; + int block_err =3D 0; =20 result =3D i2c_imx_prepare_read(i2c_imx, msgs, false); if (result) @@ -1436,8 +1437,20 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct= *i2c_imx, */ if ((!i) && block_data) { len =3D imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); - if ((len =3D=3D 0) || (len > I2C_SMBUS_BLOCK_MAX)) - return -EPROTO; + if ((len =3D=3D 0) || (len > I2C_SMBUS_BLOCK_MAX)) { + /* + * SMBus 3.1 6.5.7: support count byte of 0. + * I2C_SMBUS_BLOCK_MAX case should not hold the SDA either. + */ + if (len > I2C_SMBUS_BLOCK_MAX) + block_err =3D -EPROTO; + temp =3D imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + temp |=3D I2CR_TXAK; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + msgs->buf[0] =3D 0; + msgs->len =3D 2; + continue; + } dev_dbg(&i2c_imx->adapter.dev, "<%s> read length: 0x%X\n", __func__, len); @@ -1485,7 +1498,7 @@ static int i2c_imx_atomic_read(struct imx_i2c_struct = *i2c_imx, "<%s> read byte: B%d=3D0x%X\n", __func__, i, msgs->buf[i]); } - return 0; + return block_err; } =20 static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *ms= gs, --=20 2.43.0 From nobody Sat Jul 25 20:54:15 2026 Received: from smtp1-g21.free.fr (smtp1-g21.free.fr [212.27.42.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EB84270552; Mon, 13 Jul 2026 18:13:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.42.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783966390; cv=none; b=Hx7ZBBHRyM76XtI1et+DpExwWCccJAX7Q+BE1OiX6UkXKwoTbZVIGw7yC+GhjpTYlm6axsA1J6OMhiMoFG8mQBkQ3zzE02OrnkOEpgYdNdgF91/tSmGYHXA5u31Nrq3P0Pka6H5PCgCEsMaXmyCeuk2QEd0gE5vgjfP+AjgZZZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783966390; c=relaxed/simple; bh=BMZ+vhPgtobVdgpPIoXknWdQobjjKPrllbsApgAJxt8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mux5pmN3skXA+oWxCQB6NHt9pLO2svgLfB6+rVn20MC5C0bXQQChJTpyRrECNkrwFkuHe7wSD54vtVtt0LaNrQuONlUdIeMX8BGyN6p2rs/AuIUeEG8LYmQM/EpuI+snGaTttPFdFZ9OUQTOekjpwKOrICwQDvE5Z0NNlFaJMOA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=free.fr; spf=pass smtp.mailfrom=free.fr; dkim=pass (2048-bit key) header.d=free.fr header.i=@free.fr header.b=E5yKJLVh; arc=none smtp.client-ip=212.27.42.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=free.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=free.fr Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=free.fr header.i=@free.fr header.b="E5yKJLVh" Received: from [127.0.1.1] (unknown [91.160.0.144]) (Authenticated sender: vjardin@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 83B48B00596; Mon, 13 Jul 2026 20:12:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=free.fr; s=smtp-20201208; t=1783966387; bh=BMZ+vhPgtobVdgpPIoXknWdQobjjKPrllbsApgAJxt8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=E5yKJLVh9tKNhLFqKhxaXAvuWAxma4CgXU+Rpvs6vvIs7GkJxxteENOoFtMjGhwO6 96L1Nu6530u+0+FlHwKAKTEzhY8FKJpaLzYWs2tejM6WXMnRVyfI5rJl4kqb1feIBQ OQiWdsGGoqKsFkVo0K1L+tHiFstkypuDVg/WMKyYOtuXlv4trcKQT6JojhBmGC/MkN ewcW2VpjldHLxmP95HoM8jX4b75huEh81j/BPSCdy/pgSlJ5xVWVNCFq3UNMtRvmZ4 O5jP1uf9CQguoaMN5VbJvNpAOAZ9B0jTcIU6d8EWjQ4MVGs2FnnicUd10YLPUF8k4S d+vNpo7doj0tg== From: Vincent Jardin Date: Mon, 13 Jul 2026 20:12:00 +0200 Subject: [PATCH v3 2/2] i2c: imx: fix locked bus on SMBus block-read of 0 (IRQ) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-2-073ac9e103a5@free.fr> References: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-0-073ac9e103a5@free.fr> In-Reply-To: <20260713-for-upstream-i2c-lx2160-fix-v1-v3-0-073ac9e103a5@free.fr> To: Oleksij Rempel , Pengutronix Kernel Team , Andi Shyti , Frank Li , Sascha Hauer , Fabio Estevam , Wolfram Sang , Kaushal Butala , Shawn Guo , Stefan Eichenberger Cc: linux-i2c@vger.kernel.org, imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Vincent Jardin , stable@vger.kernel.org, Carlos Song , Stefan Eichenberger X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783966324; l=2467; i=vjardin@free.fr; s=20260525; h=from:subject:message-id; bh=BMZ+vhPgtobVdgpPIoXknWdQobjjKPrllbsApgAJxt8=; b=tEpcNDy/WD7oBzxzurloMnb3Lz2JSE6vr6RkEyKGNTRld015ZiA3WQ6JcS0g17nwym3gt91lo uJocDEgoS7MBe8+BoRQyDzjOd5g5FO5MKNZL1xrGeCY8TYNCkt9uaji X-Developer-Key: i=vjardin@free.fr; a=ed25519; pk=hppgLeFpGpKOi7LNwGEZ4jOYofJCoGd4Jf1ltAabiLw= SMBus 3.1 6.5.7 allows a Block Read byte count of 0, but the interrupt-driven block-read state machine 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 of this i2c controller. Accept count=3D0: NACK the in-flight dummy byte (TXAK) and set msg->len to 2 so i2c_imx_isr_read_continue() emits STOP via its normal last-byte path. The dummy byte is discarded; block-read callers only consume buf[0..count-1]. Reading I2DR has likewise already armed the next byte on the count > I2C_SMBUS_BLOCK_MAX error path, so NACK it (TXAK) before aborting with -EPROTO; otherwise the failing transfer's STOP cannot complete and the bus stays held. The atomic path regressed earlier (v3.16) and is fixed separately; this patch covers only the v6.13 state-machine rework. Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode") Cc: stable@vger.kernel.org # v6.13+ Acked-by: Oleksij Rempel Acked-by: Carlos Song Reviewed-by: Stefan Eichenberger Signed-off-by: Vincent Jardin --- drivers/i2c/busses/i2c-imx.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index cfd1e63359e7..d5e6e2eca3b3 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1061,11 +1061,28 @@ static inline enum imx_i2c_state i2c_imx_isr_read_c= ontinue(struct imx_i2c_struct static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *= i2c_imx) { u8 len =3D imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + unsigned int temp; =20 if (len =3D=3D 0 || len > I2C_SMBUS_BLOCK_MAX) { + /* + * SMBus 3.1 6.5.7: support count byte of 0. + * I2C_SMBUS_BLOCK_MAX case should not hold the SDA either. + * So NACK it (TXAK) to not hold the bus. + */ + temp =3D imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + temp |=3D I2CR_TXAK; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + + if (len =3D=3D 0) { + i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] =3D 0; + i2c_imx->msg->len =3D 2; + return; + } + i2c_imx->isr_result =3D -EPROTO; i2c_imx->state =3D IMX_I2C_STATE_FAILED; wake_up(&i2c_imx->queue); + return; } i2c_imx->msg->len +=3D len; i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] =3D len; --=20 2.43.0