aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJassi Brar <jassi.brar@samsung.com>2009-11-04 23:44:33 -0500
committerBen Dooks <ben-linux@fluff.org>2009-11-09 18:51:03 -0500
commit9b08284bf22f438baa2d6b68015ff17ddb431a61 (patch)
treee264f4a7dcaaac278f7978390f062cc8a663ab99
parent7507f39c57d4a285aea11c379fbc65c2b3f375ef (diff)
ARM: S3C64XX: DMA: Callback with correct buffer pointer
buffdone callback should be called per buffer request with pointer to the latest serviced request. 'next' should point to the one next to currently active. Signed-off-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
-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 a94281bb84d..7d12eb8fa58 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;