From nobody Mon Jun 8 22:55:41 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 B37493F65E6; Mon, 25 May 2026 16:44:04 +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=1779727446; cv=none; b=QuZYkwbPjoboz8PTqp8vxNcr4uXbNjaRJiqvk+dAuszmL6eq8wDYhtO6JqvoepNw3p01qClwhPd5yXiktTSTge/68p/ooVuMBbk9QHWcydR6YBMgakdenAMu0FCkuNadWtINg32kGob6P2jxjLYgOuK94wRQItxyLrdVm9rUGhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779727446; c=relaxed/simple; bh=rzAwvzxsxKzEnt4m30L3+ytuVPZEefYO/V4SO13FXGs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FkIWKMc/bvV1YIf+aMJJeyaMaVBVVVmnU0W3pDjjAtytq9Cn/cCry5GjWGPai4SsmK7MbhOybUSNzo+PeucnxwRprs/8O5zFrtw6oRNUdZVo9/CHs+EJx0NGsFh5h6R6bYMlRwkNS449F0PhBDueE0MGx4VUis92GwDpVQgCH0g= 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=Vyj99mcZ; 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="Vyj99mcZ" 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 C8ED6B00596; Mon, 25 May 2026 18:43:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=free.fr; s=smtp-20201208; t=1779727443; bh=rzAwvzxsxKzEnt4m30L3+ytuVPZEefYO/V4SO13FXGs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Vyj99mcZucMWi4AZd2mKvNWtUYRYkmiNJjRVeEAWuBeblP893DMINcwFYv/awbnP1 xXp4ytD++WaJMWO5TIZJFJcGbF+W8DyzeEIAIJ/d5F2XJVHNqELkFyJ7eSHgpvfVmG GAIisF9njFG0QlKcy0f6Jul/nxSIQJjtZHitWXIV5S6+Tgowrtevk5AxctvqVwfaaR 1x6LuG2ivaFcp44kFbTLL1bWBzMw/8iCA1R/bxnVv2CTU6h9WlSd4jrzO0pMGLnpdh /8OPHA3UpFTiJbQnjdi6OB5ITNsfy64DwNZTu0Nc0SjDjLd6+oa67GW9WAU+5xpX78 JS1QujvOsAKwA== From: Vincent Jardin Date: Mon, 25 May 2026 18:43:15 +0200 Subject: [PATCH v2 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: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-1-26a3cc8cd055@free.fr> References: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-0-26a3cc8cd055@free.fr> In-Reply-To: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-0-26a3cc8cd055@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 X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1779727406; l=2733; i=vjardin@free.fr; s=20260525; h=from:subject:message-id; bh=rzAwvzxsxKzEnt4m30L3+ytuVPZEefYO/V4SO13FXGs=; b=FaP3kDdQRLS4KMCFoV9lObFeMe4eJfn8XGuHo6rGQYRK72nqpeMEiqacXbgS8I8SOxOKMonvB TcTp143bP5VAlBckyluXXr9pt+7d6Er0SNKVttFuzcd1zO52i7tIEiz 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: # v3.16+ 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 a208fefd3c3b..14107e1ad413 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 Mon Jun 8 22:55:41 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 32EE63F5BC5; Mon, 25 May 2026 16:44:23 +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=1779727464; cv=none; b=gH/6CynuC1fnVIFueZxP/Ng76jYjDQ+350gRlECJNyeC2zh8drWOsUTNrx0uRmcOJcY6IERxjAmtsEuZAcbYT3WxNz2WKRksvRH2Gl4wUwIBc7Wul0VXSYZasbnRaplc7MO+KrlWBXmn1ymaqtnMn1Gs11Dfuaj2BYlBUf/uTVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779727464; c=relaxed/simple; bh=TCAfUvjhaCsJQTrEtvumpIoh8l6kyRt90adoFjnNFWM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IxCTIePcdbvhpFVOM9ZAMbg+JK/HIAQ5SDUgAINm471iyBPiEixurcQfVeHAJ4wJOSbfmOdkLLL0xh87Gohq1IdhY7Dw54OYBGcNEa1OZuU3RryQrqM5317gjn2WB7SPDwpOHQGqNyWQgRQCXD0A2zBN3OfUz9tkHFMvI+5kGJc= 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=I9CarSYq; 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="I9CarSYq" 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 7ED5DB00583; Mon, 25 May 2026 18:44:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=free.fr; s=smtp-20201208; t=1779727462; bh=TCAfUvjhaCsJQTrEtvumpIoh8l6kyRt90adoFjnNFWM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=I9CarSYqcmzd2yYyH7i0zq6pF9GGeyuQwRNYOhd/xQob2TF69kwI+ImCUNTskjvhq iLpdbcbFRCZ1nuIGX1rPkBgk4Y5gp7cnapKaoabO6Te/JsvD57o+Ym7XZxg7W0fUQY Gsg4YZAR72eI1uqqoW5MBJsq9W4mInSHgqbNfMVor1iSHPbMQ54BVx3qLZb7ey4FzQ poewztBNQxkIb4Yl1FD+rV/DKEY5uEWNnjqsO5SJqqdSff32efcwsF22CwFJ+quFfg UIoflOsiIqlZ5b9YDIEme68/lbFqTJOZnOYlAy6SlaD49OeP4xwcqFGSJkAWG/OEwK 6nQG0hXzoNvBw== From: Vincent Jardin Date: Mon, 25 May 2026 18:43:16 +0200 Subject: [PATCH v2 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: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-2-26a3cc8cd055@free.fr> References: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-0-26a3cc8cd055@free.fr> In-Reply-To: <20260525-for-upstream-i2c-lx2160-fix-v1-v2-0-26a3cc8cd055@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 X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1779727406; l=2318; i=vjardin@free.fr; s=20260525; h=from:subject:message-id; bh=TCAfUvjhaCsJQTrEtvumpIoh8l6kyRt90adoFjnNFWM=; b=MUBeVu7lKe21R2tFAurHFC1df7bUtHKMOZ6EGsW6DipVT90oy1nihPhSo2orpgGz8ubZBeVPE pbaPh6u7oVvCUMpuW9iszwfnGvUEMEyeYQsW0rLAjTW8cE6J4IDiTVk 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: # v6.13+ 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 14107e1ad413..8db8d2e10f5c 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