Skip to content

Commit 82c6d49

Browse files
Esben Haabendalgregkh
authored andcommitted
i2c: imx: Fix race condition in dma read
commit bed4ff1 upstream. This fixes a race condition, where the DMAEN bit ends up being set after I2C slave has transmitted a byte following the dummy read. When that happens, an interrupt is generated instead, and no DMA request is generated to kickstart the DMA read, and a timeout happens after DMA_TIMEOUT (1 sec). Fixed by setting the DMAEN bit before the dummy read. Signed-off-by: Esben Haabendal <eha@deif.com> Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 415a02d commit 82c6d49

1 file changed

Lines changed: 4 additions & 4 deletions

File tree

drivers/i2c/busses/i2c-imx.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
665665
struct imx_i2c_dma *dma = i2c_imx->dma;
666666
struct device *dev = &i2c_imx->adapter.dev;
667667

668-
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
669-
temp |= I2CR_DMAEN;
670-
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
671668

672669
dma->chan_using = dma->chan_rx;
673670
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -780,6 +777,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
780777
int i, result;
781778
unsigned int temp;
782779
int block_data = msgs->flags & I2C_M_RECV_LEN;
780+
int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data;
783781

784782
dev_dbg(&i2c_imx->adapter.dev,
785783
"<%s> write slave address: addr=0x%x\n",
@@ -806,12 +804,14 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
806804
*/
807805
if ((msgs->len - 1) || block_data)
808806
temp &= ~I2CR_TXAK;
807+
if (use_dma)
808+
temp |= I2CR_DMAEN;
809809
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
810810
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
811811

812812
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
813813

814-
if (i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data)
814+
if (use_dma)
815815
return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
816816

817817
/* read data */

0 commit comments

Comments
 (0)