aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-s3c64xx/dma.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/arch/arm/plat-s3c64xx/dma.c b/arch/arm/plat-s3c64xx/dma.c
index a94281bb84d6..7d12eb8fa58d 100644
--- a/arch/arm/plat-s3c64xx/dma.c
+++ b/arch/arm/plat-s3c64xx/dma.c
@@ -576,6 +576,7 @@ static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
576 errstat = readl(dmac->regs + PL080_ERR_STATUS); 576 errstat = readl(dmac->regs + PL080_ERR_STATUS);
577 577
578 for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) { 578 for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
579 struct s3c64xx_dma_buff *buff;
579 580
580 if (!(errstat & bit) && !(tcstat & bit)) 581 if (!(errstat & bit) && !(tcstat & bit))
581 continue; 582 continue;
@@ -591,7 +592,33 @@ static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
591 if (errstat & bit) 592 if (errstat & bit)
592 writel(bit, dmac->regs + PL080_ERR_CLEAR); 593 writel(bit, dmac->regs + PL080_ERR_CLEAR);
593 594
594 s3c64xx_dma_bufffdone(chan, chan->curr, res); 595 /* 'next' points to the buffer that is next to the
596 * currently active buffer.
597 * For CIRCULAR queues, 'next' will be same as 'curr'
598 * when 'end' is the active buffer.
599 */
600 buff = chan->curr;
601 while (buff && buff != chan->next
602 && buff->next != chan->next)
603 buff = buff->next;
604
605 if (!buff)
606 BUG();
607
608 if (buff == chan->next)
609 buff = chan->end;
610
611 s3c64xx_dma_bufffdone(chan, buff, res);
612
613 /* Update 'next' */
614 buff = chan->next;
615 if (chan->next == chan->end) {
616 chan->next = chan->curr;
617 if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
618 chan->end = NULL;
619 } else {
620 chan->next = buff->next;
621 }
595 } 622 }
596 623
597 return IRQ_HANDLED; 624 return IRQ_HANDLED;