Skip to content

Commit dbf590b

Browse files
neosys007miquelraynal
authored andcommitted
mtd: rawnand: lpc32xx_mlc: fail DMA transfers on timeout
lpc32xx_xmit_dma() starts a DMA transfer and waits up to one second for its completion, but it ignores the wait result and returns success after unmapping the buffer. A timed out read can therefore return success with incomplete data, and a timed out write can continue the NAND operation without proof that the DMA payload reached the controller. Terminate the DMA channel on timeout, unmap the scatterlist through the existing cleanup path, and return -ETIMEDOUT to the NAND read/write callers. Initialize the shared cleanup-path result before using it for dmaengine_prep_slave_sg() failures. Fixes: 70f7cb7 ("mtd: add LPC32xx MLC NAND driver") Cc: stable@vger.kernel.org Reviewed-by: Vladimir Zapolskiy <vz@kernel.org> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
1 parent 9d4af74 commit dbf590b

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

drivers/mtd/nand/raw/lpc32xx_mlc.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
396396
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
397397
struct dma_async_tx_descriptor *desc;
398398
int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
399+
unsigned long time_left;
399400
int res;
400401

401402
sg_init_one(&host->sgl, mem, len);
@@ -410,6 +411,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
410411
flags);
411412
if (!desc) {
412413
dev_err(mtd->dev.parent, "Failed to prepare slave sg\n");
414+
res = -ENXIO;
413415
goto out1;
414416
}
415417

@@ -420,15 +422,21 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
420422
dmaengine_submit(desc);
421423
dma_async_issue_pending(host->dma_chan);
422424

423-
wait_for_completion_timeout(&host->comp_dma, msecs_to_jiffies(1000));
425+
time_left = wait_for_completion_timeout(&host->comp_dma,
426+
msecs_to_jiffies(1000));
427+
if (!time_left) {
428+
dmaengine_terminate_sync(host->dma_chan);
429+
res = -ETIMEDOUT;
430+
goto out1;
431+
}
424432

425433
dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
426434
DMA_BIDIRECTIONAL);
427435
return 0;
428436
out1:
429437
dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
430438
DMA_BIDIRECTIONAL);
431-
return -ENXIO;
439+
return res;
432440
}
433441

434442
static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf,

0 commit comments

Comments
 (0)