* [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length
@ 2026-01-16 11:19 LI Qingwu
2026-01-16 11:19 ` [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler LI Qingwu
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: LI Qingwu @ 2026-01-16 11:19 UTC (permalink / raw)
To: o.rempel, kernel, andi.shyti, shawnguo, s.hauer, festevam,
linux-i2c, imx, linux-arm-kernel, linux-kernel
Cc: bsp-development.geo, LI Qingwu
This series fixes a crash and bus lockup when SMBus block read operations
encounter invalid length values (zero or greater than I2C_SMBUS_BLOCK_MAX).
Both patches have been tested on i.MX 8M Plus with continuous block read
operations from battery and keyboard devices sharing the same I2C bus.
Changes in v3:
- Add trailing comma to IMX_I2C_STATE_READ_BLOCK_DATA_ABORT enum
- Clean up reference manual citations
LI Qingwu (2):
i2c: imx: preserve error state in block data length handler
i2c: imx: add abort path for invalid block length
drivers/i2c/busses/i2c-imx.c | 58 ++++++++++++++++++++++++++++++++++--
1 file changed, 55 insertions(+), 3 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler 2026-01-16 11:19 [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length LI Qingwu @ 2026-01-16 11:19 ` LI Qingwu 2026-01-22 10:48 ` Andi Shyti 2026-01-16 11:19 ` [PATCH V3 2/2] i2c: imx: add abort path for invalid block length LI Qingwu 2026-01-28 22:19 ` [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length Andi Shyti 2 siblings, 1 reply; 6+ messages in thread From: LI Qingwu @ 2026-01-16 11:19 UTC (permalink / raw) To: o.rempel, kernel, andi.shyti, shawnguo, s.hauer, festevam, linux-i2c, imx, linux-arm-kernel, linux-kernel Cc: bsp-development.geo, LI Qingwu When a block read returns an invalid length, zero or >I2C_SMBUS_BLOCK_MAX, the length handler sets the state to IMX_I2C_STATE_FAILED. However, i2c_imx_master_isr() unconditionally overwrites this with IMX_I2C_STATE_READ_CONTINUE, causing an endless read loop that overruns buffers and crashes the system. Guard the state transition to preserve error states set by the length handler. Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn> --- drivers/i2c/busses/i2c-imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 205cc132fdec..05ba41144648 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1102,7 +1102,8 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i case IMX_I2C_STATE_READ_BLOCK_DATA_LEN: i2c_imx_isr_read_block_data_len(i2c_imx); - i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; + if (i2c_imx->state == IMX_I2C_STATE_READ_BLOCK_DATA_LEN) + i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; break; case IMX_I2C_STATE_WRITE: -- 2.43.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler 2026-01-16 11:19 ` [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler LI Qingwu @ 2026-01-22 10:48 ` Andi Shyti 2026-01-22 12:18 ` Stefan Eichenberger 0 siblings, 1 reply; 6+ messages in thread From: Andi Shyti @ 2026-01-22 10:48 UTC (permalink / raw) To: LI Qingwu Cc: o.rempel, kernel, shawnguo, Stefan Eichenberger, s.hauer, festevam, linux-i2c, imx, linux-arm-kernel, linux-kernel, bsp-development.geo Hi Li, I'm adding also Stefan in the Cc list as he has authored the lines you are changing. On Fri, Jan 16, 2026 at 11:19:05AM +0000, LI Qingwu wrote: > When a block read returns an invalid length, zero or >I2C_SMBUS_BLOCK_MAX, > the length handler sets the state to IMX_I2C_STATE_FAILED. However, > i2c_imx_master_isr() unconditionally overwrites this with > IMX_I2C_STATE_READ_CONTINUE, causing an endless read loop that overruns > buffers and crashes the system. > > Guard the state transition to preserve error states set by the length > handler. > > Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn> I asked you to add the Fixes tag here. Perhaps you need to add: Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode") Cc Stefan Eichenberger <stefan.eichenberger@toradex.com> Cc: <stable@vger.kernel.org> # v6.13+ You can get the information above with "git blame". I'll wait for comments from Oleksij and/or Stefan here. Andi > --- > drivers/i2c/busses/i2c-imx.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c > index 205cc132fdec..05ba41144648 100644 > --- a/drivers/i2c/busses/i2c-imx.c > +++ b/drivers/i2c/busses/i2c-imx.c > @@ -1102,7 +1102,8 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i > > case IMX_I2C_STATE_READ_BLOCK_DATA_LEN: > i2c_imx_isr_read_block_data_len(i2c_imx); > - i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; > + if (i2c_imx->state == IMX_I2C_STATE_READ_BLOCK_DATA_LEN) > + i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; > break; > > case IMX_I2C_STATE_WRITE: > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler 2026-01-22 10:48 ` Andi Shyti @ 2026-01-22 12:18 ` Stefan Eichenberger 0 siblings, 0 replies; 6+ messages in thread From: Stefan Eichenberger @ 2026-01-22 12:18 UTC (permalink / raw) To: Andi Shyti Cc: LI Qingwu, o.rempel, kernel, shawnguo, Stefan Eichenberger, s.hauer, festevam, linux-i2c, imx, linux-arm-kernel, linux-kernel, bsp-development.geo Hi Andi and Li, On Thu, Jan 22, 2026 at 11:48:54AM +0100, Andi Shyti wrote: > Hi Li, > > I'm adding also Stefan in the Cc list as he has authored the > lines you are changing. > > On Fri, Jan 16, 2026 at 11:19:05AM +0000, LI Qingwu wrote: > > When a block read returns an invalid length, zero or >I2C_SMBUS_BLOCK_MAX, > > the length handler sets the state to IMX_I2C_STATE_FAILED. However, > > i2c_imx_master_isr() unconditionally overwrites this with > > IMX_I2C_STATE_READ_CONTINUE, causing an endless read loop that overruns > > buffers and crashes the system. > > > > Guard the state transition to preserve error states set by the length > > handler. > > > > Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn> > > I asked you to add the Fixes tag here. Perhaps you need to add: > > Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode") > Cc Stefan Eichenberger <stefan.eichenberger@toradex.com> > Cc: <stable@vger.kernel.org> # v6.13+ > > You can get the information above with "git blame". > > I'll wait for comments from Oleksij and/or Stefan here. > > Andi > > > --- > > drivers/i2c/busses/i2c-imx.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c > > index 205cc132fdec..05ba41144648 100644 > > --- a/drivers/i2c/busses/i2c-imx.c > > +++ b/drivers/i2c/busses/i2c-imx.c > > @@ -1102,7 +1102,8 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i > > > > case IMX_I2C_STATE_READ_BLOCK_DATA_LEN: > > i2c_imx_isr_read_block_data_len(i2c_imx); > > - i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; > > + if (i2c_imx->state == IMX_I2C_STATE_READ_BLOCK_DATA_LEN) > > + i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; > > break; > > > > case IMX_I2C_STATE_WRITE: > > -- > > 2.43.0 > > It looks good to me, thanks for the fix. I wonder if the functions in the isr should instead better return a status and based on that we decide if we have to change the state or not. Then we would have the decision to what state we swtich at one place. However, this would probably be too much rework for that fix. Therefore, if you add the fixes tag suggested by Andi: Reviewed-by: Stefan Eichenberger <eichest@gmail.com> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH V3 2/2] i2c: imx: add abort path for invalid block length 2026-01-16 11:19 [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length LI Qingwu 2026-01-16 11:19 ` [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler LI Qingwu @ 2026-01-16 11:19 ` LI Qingwu 2026-01-28 22:19 ` [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length Andi Shyti 2 siblings, 0 replies; 6+ messages in thread From: LI Qingwu @ 2026-01-16 11:19 UTC (permalink / raw) To: o.rempel, kernel, andi.shyti, shawnguo, s.hauer, festevam, linux-i2c, imx, linux-arm-kernel, linux-kernel Cc: bsp-development.geo, LI Qingwu When a block read returns an invalid length (0 or >I2C_SMBUS_BLOCK_MAX), the current implementation leaves the bus hanging with SDA held low, blocking all further I2C communication on the bus. Add a dedicated IMX_I2C_STATE_READ_BLOCK_DATA_ABORT state and ISR handler to properly terminate the transfer when an invalid block length is detected: - Set TXAK and receive the next byte with NACK - On the following interrupt, generate a Stop condition - Read and discard the final byte - Report -EPROTO to the caller This ensures the bus is released correctly and allows other devices on the bus to continue operating normally. Tested on i.MX 8M Plus with continuous block read operations. Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn> --- drivers/i2c/busses/i2c-imx.c | 55 ++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 05ba41144648..d3fbc2df7f04 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -232,6 +232,7 @@ enum imx_i2c_state { IMX_I2C_STATE_READ_CONTINUE, IMX_I2C_STATE_READ_BLOCK_DATA, IMX_I2C_STATE_READ_BLOCK_DATA_LEN, + IMX_I2C_STATE_READ_BLOCK_DATA_ABORT, }; struct imx_i2c_struct { @@ -1053,14 +1054,60 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); } +static inline void i2c_imx_isr_read_block_data_abort(struct imx_i2c_struct *i2c_imx) +{ + unsigned int temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + + if (i2c_imx->is_lastmsg) { + /* + * Last byte to read. + * + * Ref: IMX8MPRM Rev. 1, 06/2021: 17.1.4.4 Generation of Stop + * + * Ref: IMX8MPRM Rev. 1, 06/2021: Figure 17-5. + * Flowchart of typical I2C interrupt routine + * + * Before the last byte is read, a Stop signal must be generated. + */ + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (!(temp & I2CR_MSTA)) + i2c_imx->stopped = 1; + temp &= ~(I2CR_MSTA | I2CR_MTX); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + i2c_imx->state = IMX_I2C_STATE_FAILED; + wake_up(&i2c_imx->queue); + } else { + /* + * Next-to-last byte to read. + * + * Ref: IMX8MPRM Rev. 1, 06/2021: 17.1.4.4 Generation of Stop + * + * Ref: IMX8MPRM Rev. 1, 06/2021: Figure 17-5. + * Flowchart of typical I2C interrupt routine + * + * For a master receiver to terminate a data transfer, it must + * inform the slave transmitter by not acknowledging the last + * data byte. This is done by setting the transmit acknowledge + * bit (I2C_I2CR[TXAK]) before reading the next-to-last byte. + */ + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + temp |= I2CR_TXAK; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + i2c_imx->is_lastmsg = true; + } +} + static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx) { u8 len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) { i2c_imx->isr_result = -EPROTO; - i2c_imx->state = IMX_I2C_STATE_FAILED; - wake_up(&i2c_imx->queue); + i2c_imx->state = IMX_I2C_STATE_READ_BLOCK_DATA_ABORT; + i2c_imx->is_lastmsg = false; + return; } i2c_imx->msg->len += len; i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len; @@ -1106,6 +1153,10 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE; break; + case IMX_I2C_STATE_READ_BLOCK_DATA_ABORT: + i2c_imx_isr_read_block_data_abort(i2c_imx); + break; + case IMX_I2C_STATE_WRITE: if (i2c_imx_isr_write(i2c_imx)) break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length 2026-01-16 11:19 [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length LI Qingwu 2026-01-16 11:19 ` [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler LI Qingwu 2026-01-16 11:19 ` [PATCH V3 2/2] i2c: imx: add abort path for invalid block length LI Qingwu @ 2026-01-28 22:19 ` Andi Shyti 2 siblings, 0 replies; 6+ messages in thread From: Andi Shyti @ 2026-01-28 22:19 UTC (permalink / raw) To: LI Qingwu Cc: o.rempel, kernel, shawnguo, s.hauer, festevam, linux-i2c, imx, linux-arm-kernel, linux-kernel, bsp-development.geo Hi Li, > LI Qingwu (2): > i2c: imx: preserve error state in block data length handler I merged this patch in i2c/i2c-host-fixes. > i2c: imx: add abort path for invalid block length For this patch I want the review from Oleksij. Oleksij? :-) Thanks, Andi ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-01-28 22:19 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-16 11:19 [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length LI Qingwu 2026-01-16 11:19 ` [PATCH V3 1/2] i2c: imx: preserve error state in block data length handler LI Qingwu 2026-01-22 10:48 ` Andi Shyti 2026-01-22 12:18 ` Stefan Eichenberger 2026-01-16 11:19 ` [PATCH V3 2/2] i2c: imx: add abort path for invalid block length LI Qingwu 2026-01-28 22:19 ` [PATCH V3 0/2] i2c: imx: Fix block read handling for invalid length Andi Shyti
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox