Skip to content

Commit 341198e

Browse files
iziumtsevvinodkoul
authored andcommitted
dmaengine: imx-dma: fix wrong callback invoke
Once the "ld_queue" list is not empty, next descriptor will migrate into "ld_active" list. The "desc" variable will be overwritten during that transition. And later the dmaengine_desc_get_callback_invoke() will use it as an argument. As result we invoke wrong callback. That behaviour was in place since: commit fcaaba6 ("dmaengine: imx-dma: fix callback path in tasklet"). But after commit 4cd13c2 ("softirq: Let ksoftirqd do its job") things got worse, since possible delay between tasklet_schedule() from DMA irq handler and actual tasklet function execution got bigger. And that gave more time for new DMA request to be submitted and to be put into "ld_queue" list. It has been noticed that DMA issue is causing problems for "mxc-mmc" driver. While stressing the system with heavy network traffic and writing/reading to/from sd card simultaneously the timeout may happen: 10013000.sdhci: mxcmci_watchdog: read time out (status = 0x30004900) That often lead to file system corruption. Signed-off-by: Leonid Iziumtsev <leonid.iziumtsev@gmail.com> Signed-off-by: Vinod Koul <vkoul@kernel.org> Cc: stable@vger.kernel.org
1 parent dc3f595 commit 341198e

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

drivers/dma/imx-dma.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data)
618618
{
619619
struct imxdma_channel *imxdmac = (void *)data;
620620
struct imxdma_engine *imxdma = imxdmac->imxdma;
621-
struct imxdma_desc *desc;
621+
struct imxdma_desc *desc, *next_desc;
622622
unsigned long flags;
623623

624624
spin_lock_irqsave(&imxdma->lock, flags);
@@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data)
648648
list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
649649

650650
if (!list_empty(&imxdmac->ld_queue)) {
651-
desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
652-
node);
651+
next_desc = list_first_entry(&imxdmac->ld_queue,
652+
struct imxdma_desc, node);
653653
list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
654-
if (imxdma_xfer_desc(desc) < 0)
654+
if (imxdma_xfer_desc(next_desc) < 0)
655655
dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
656656
__func__, imxdmac->channel);
657657
}

0 commit comments

Comments
 (0)