Skip to content

Commit 5190417

Browse files
tq-schiffermwsakernel
authored andcommitted
i2c: mxs: ensure that DMA buffers are safe for DMA
We found that after commit 9c46929 ("ARM: implement THREAD_INFO_IN_TASK for uniprocessor systems"), the PCF85063 RTC driver stopped working on i.MX28 due to regmap_bulk_read() reading bogus data into a stack buffer. This is caused by the i2c-mxs driver using DMA transfers even for messages without the I2C_M_DMA_SAFE flag, and the aforementioned commit enabling vmapped stacks. As the MXS I2C controller requires DMA for reads of >4 bytes, DMA can't be disabled, so the issue is fixed by using i2c_get_dma_safe_msg_buf() to create a bounce buffer when needed. Fixes: 9c46929 ("ARM: implement THREAD_INFO_IN_TASK for uniprocessor systems") Signed-off-by: Matthias Schiffer <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 1c78850 commit 5190417

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

drivers/i2c/busses/i2c-mxs.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ static void mxs_i2c_dma_irq_callback(void *param)
171171
}
172172

173173
static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
174-
struct i2c_msg *msg, uint32_t flags)
174+
struct i2c_msg *msg, u8 *buf, uint32_t flags)
175175
{
176176
struct dma_async_tx_descriptor *desc;
177177
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
@@ -226,7 +226,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
226226
}
227227

228228
/* Queue the DMA data transfer. */
229-
sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
229+
sg_init_one(&i2c->sg_io[1], buf, msg->len);
230230
dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
231231
desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
232232
DMA_DEV_TO_MEM,
@@ -259,7 +259,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
259259
/* Queue the DMA data transfer. */
260260
sg_init_table(i2c->sg_io, 2);
261261
sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
262-
sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
262+
sg_set_buf(&i2c->sg_io[1], buf, msg->len);
263263
dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
264264
desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
265265
DMA_MEM_TO_DEV,
@@ -563,6 +563,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
563563
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
564564
int ret;
565565
int flags;
566+
u8 *dma_buf;
566567
int use_pio = 0;
567568
unsigned long time_left;
568569

@@ -588,13 +589,20 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
588589
if (ret && (ret != -ENXIO))
589590
mxs_i2c_reset(i2c);
590591
} else {
592+
dma_buf = i2c_get_dma_safe_msg_buf(msg, 1);
593+
if (!dma_buf)
594+
return -ENOMEM;
595+
591596
reinit_completion(&i2c->cmd_complete);
592-
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
593-
if (ret)
597+
ret = mxs_i2c_dma_setup_xfer(adap, msg, dma_buf, flags);
598+
if (ret) {
599+
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
594600
return ret;
601+
}
595602

596603
time_left = wait_for_completion_timeout(&i2c->cmd_complete,
597604
msecs_to_jiffies(1000));
605+
i2c_put_dma_safe_msg_buf(dma_buf, msg, true);
598606
if (!time_left)
599607
goto timeout;
600608

0 commit comments

Comments
 (0)