* [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged
@ 2026-11-13 7:32 Mehmet Fide
2026-11-13 7:32 ` [PATCH 1/2] i2c: imx: do not carry the interrupt status over to the next transfer Mehmet Fide
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Mehmet Fide @ 2026-11-13 7:32 UTC (permalink / raw)
To: Andi Shyti, Oleksij Rempel
Cc: Pengutronix Kernel Team, Frank Li, Sascha Hauer, Fabio Estevam,
Yao Yuan, Wolfram Sang, linux-i2c, imx, linux-arm-kernel,
linux-kernel, stable
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
A write of DMA_THRESHOLD bytes or more to an address that does not
answer leaves the interrupt status behind, so that the next DMA read
returns 0xff for every byte without an error (patch 1), and it blocks
for DMA_TIMEOUT before it fails with -ETIMEDOUT instead of -ENXIO
(patch 2). Patch 2 needs patch 1.
Tested on a Colibri VF50 (i2c0 at 100 kHz, DMA) with v6.12.117, where
the touched code is the same; on this base compile tested only (W=1,
sparse). 200 rounds of failed write, 32 byte read and acknowledged
18 byte write: 200 times ENXIO at once, no wrong read, every write
acknowledged.
Mehmet Fide (2):
i2c: imx: do not carry the interrupt status over to the next transfer
i2c: imx: return -ENXIO at once when a DMA write is not acknowledged
drivers/i2c/busses/i2c-imx.c | 10 ++++++++++
1 file changed, 10 insertions(+)
base-commit: 25e7ab89f4774b0f842cee0e8a20c11f755924d5
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 1/2] i2c: imx: do not carry the interrupt status over to the next transfer
2026-11-13 7:32 [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged Mehmet Fide
@ 2026-11-13 7:32 ` Mehmet Fide
2026-11-13 7:32 ` [PATCH 2/2] i2c: imx: return -ENXIO at once when a DMA write is not acknowledged Mehmet Fide
2026-11-13 8:02 ` [PATCH 0/2] i2c: imx: two fixes for a DMA write that " Mehmet Fide
2 siblings, 0 replies; 4+ messages in thread
From: Mehmet Fide @ 2026-11-13 7:32 UTC (permalink / raw)
To: Andi Shyti, Oleksij Rempel
Cc: Pengutronix Kernel Team, Frank Li, Sascha Hauer, Fabio Estevam,
Yao Yuan, Wolfram Sang, linux-i2c, imx, linux-arm-kernel,
linux-kernel, stable
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
In DMA mode the interrupt handler stores I2SR in i2c_imx->i2csr and only
i2c_imx_trx_complete() clears it. A DMA transfer that fails returns
without doing so, for example a DMA write whose address is not
acknowledged.
The stale status stays until the next DMA read. There
i2c_imx_prepare_read() calls i2c_imx_trx_complete(), which finds IIF set
and returns before the address byte has been sent, so the read returns
0xff for every byte without an error:
i2ctransfer -a -y 0 w20@0x03 0x00- # unused address, -ETIMEDOUT
i2ctransfer -y 0 w1@0x54 0x00 r32 # 32 times 0xff
i2ctransfer -y 0 w1@0x54 0x00 r32 # correct data
Clear the status when a transfer starts.
Fixes: ce1a78840ff7 ("i2c: imx: add DMA support for freescale i2c driver")
Cc: stable@vger.kernel.org
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
drivers/i2c/busses/i2c-imx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index ccf08cd63151..1987a0fd8132 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1657,6 +1657,8 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
if (result)
return result;
+ i2c_imx->i2csr = 0;
+
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx, atomic);
if (result) {
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/2] i2c: imx: return -ENXIO at once when a DMA write is not acknowledged
2026-11-13 7:32 [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged Mehmet Fide
2026-11-13 7:32 ` [PATCH 1/2] i2c: imx: do not carry the interrupt status over to the next transfer Mehmet Fide
@ 2026-11-13 7:32 ` Mehmet Fide
2026-11-13 8:02 ` [PATCH 0/2] i2c: imx: two fixes for a DMA write that " Mehmet Fide
2 siblings, 0 replies; 4+ messages in thread
From: Mehmet Fide @ 2026-11-13 7:32 UTC (permalink / raw)
To: Andi Shyti, Oleksij Rempel
Cc: Pengutronix Kernel Team, Frank Li, Sascha Hauer, Fabio Estevam,
Yao Yuan, Wolfram Sang, linux-i2c, imx, linux-arm-kernel,
linux-kernel, stable
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
When the address of a DMA write is not acknowledged the controller
raises its interrupt and no DMA request, so i2c_imx_dma_write() blocks
for DMA_TIMEOUT (1 s) and returns -ETIMEDOUT, where the interrupt driven
write returns -ENXIO.
Let the interrupt handler end the wait when it sees a missing
acknowledge during a DMA write, and return -ENXIO. No interrupt arrives
while the bytes of a DMA write are acknowledged, so that path does not
change.
Fixes: ce1a78840ff7 ("i2c: imx: add DMA support for freescale i2c driver")
Cc: stable@vger.kernel.org
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
drivers/i2c/busses/i2c-imx.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 1987a0fd8132..09934f3b13ef 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1108,6 +1108,9 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i
switch (i2c_imx->state) {
case IMX_I2C_STATE_DMA:
i2c_imx->i2csr = status;
+ if ((status & I2SR_RXAK) &&
+ i2c_imx->dma->dma_transfer_dir == DMA_MEM_TO_DEV)
+ complete(&i2c_imx->dma->cmd_complete);
wake_up(&i2c_imx->queue);
break;
@@ -1225,6 +1228,11 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
return -ETIMEDOUT;
}
+ if (i2c_imx->i2csr & I2SR_RXAK) {
+ dmaengine_terminate_sync(dma->chan_using);
+ return -ENXIO;
+ }
+
/* Waiting for transfer complete. */
while (1) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged
2026-11-13 7:32 [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged Mehmet Fide
2026-11-13 7:32 ` [PATCH 1/2] i2c: imx: do not carry the interrupt status over to the next transfer Mehmet Fide
2026-11-13 7:32 ` [PATCH 2/2] i2c: imx: return -ENXIO at once when a DMA write is not acknowledged Mehmet Fide
@ 2026-11-13 8:02 ` Mehmet Fide
2 siblings, 0 replies; 4+ messages in thread
From: Mehmet Fide @ 2026-11-13 8:02 UTC (permalink / raw)
To: Andi Shyti, Oleksij Rempel
Cc: Pengutronix Kernel Team, Frank Li, Sascha Hauer, Fabio Estevam,
Yao Yuan, Wolfram Sang, linux-i2c, imx, linux-arm-kernel,
linux-kernel, stable
A correction to the test note in this cover letter.
The v6.12.117 kernel I tested with is not plain stable. It carries a
backport of commit 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non
dma mode"), so its i2c-imx.c has the interrupt state machine of
mainline. "The touched code is the same" is true for that tree only.
For stable: both patches apply to 6.18.y and 7.3.y. On 6.12.y and older
patch 1 applies with fuzz and patch 2 does not apply, as the interrupt
handler is different there. I can send backports for those trees once
the patches are in mainline.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-13 8:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 7:32 [PATCH 0/2] i2c: imx: two fixes for a DMA write that is not acknowledged Mehmet Fide
2026-11-13 7:32 ` [PATCH 1/2] i2c: imx: do not carry the interrupt status over to the next transfer Mehmet Fide
2026-11-13 7:32 ` [PATCH 2/2] i2c: imx: return -ENXIO at once when a DMA write is not acknowledged Mehmet Fide
2026-11-13 8:02 ` [PATCH 0/2] i2c: imx: two fixes for a DMA write that " Mehmet Fide
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®