aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorRussell King - ARM Linux <linux@arm.linux.org.uk>2011-01-03 17:45:17 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-04 22:16:14 -0500
commit8087aacda040bdbf84940712d132ce80c30b9d5d (patch)
tree3a59272bc4555eae854a012940a36f80a8f4c1a5 /drivers/dma
parent501e67e82dee68d0a594ec0549f3d6a2943c91f5 (diff)
ARM: PL08x: introduce 'phychan_hold' to hold on to physical channels
Introduce 'phychan_hold' to hold on to physical DMA channels while we're preparing a new descriptor for it. This will be incremented when we allocate a physical channel and set the MUX registers during the preparation of the TXD, and will only be decremented when the TXD is submitted. This prevents the physical channel being given up before the new TXD is placed on the queue. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/amba-pl08x.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 650e2bbc7aa..bf6f7d02c9f 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -959,6 +959,7 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
959 ch->signal, 959 ch->signal,
960 plchan->name); 960 plchan->name);
961 961
962 plchan->phychan_hold++;
962 plchan->phychan = ch; 963 plchan->phychan = ch;
963 964
964 return 0; 965 return 0;
@@ -998,6 +999,8 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
998 /* Do this memcpy whenever there is a channel ready */ 999 /* Do this memcpy whenever there is a channel ready */
999 plchan->state = PL08X_CHAN_WAITING; 1000 plchan->state = PL08X_CHAN_WAITING;
1000 plchan->waiting = txd; 1001 plchan->waiting = txd;
1002 } else {
1003 plchan->phychan_hold--;
1001 } 1004 }
1002 1005
1003 /* This unlock follows the lock in the prep() function */ 1006 /* This unlock follows the lock in the prep() function */
@@ -1585,6 +1588,7 @@ static void pl08x_tasklet(unsigned long data)
1585 */ 1588 */
1586 plchan->lc = txd->tx.cookie; 1589 plchan->lc = txd->tx.cookie;
1587 } 1590 }
1591
1588 /* 1592 /*
1589 * If a new descriptor is queued, set it up 1593 * If a new descriptor is queued, set it up
1590 * plchan->at is NULL here 1594 * plchan->at is NULL here
@@ -1598,6 +1602,12 @@ static void pl08x_tasklet(unsigned long data)
1598 list_del(&next->node); 1602 list_del(&next->node);
1599 1603
1600 pl08x_start_txd(plchan, next); 1604 pl08x_start_txd(plchan, next);
1605 } else if (plchan->phychan_hold) {
1606 /*
1607 * This channel is still in use - we have a new txd being
1608 * prepared and will soon be queued. Don't give up the
1609 * physical channel.
1610 */
1601 } else { 1611 } else {
1602 struct pl08x_dma_chan *waiting = NULL; 1612 struct pl08x_dma_chan *waiting = NULL;
1603 1613
@@ -1625,6 +1635,7 @@ static void pl08x_tasklet(unsigned long data)
1625 ret = prep_phy_channel(waiting, 1635 ret = prep_phy_channel(waiting,
1626 waiting->waiting); 1636 waiting->waiting);
1627 BUG_ON(ret); 1637 BUG_ON(ret);
1638 waiting->phychan_hold--;
1628 waiting->state = PL08X_CHAN_RUNNING; 1639 waiting->state = PL08X_CHAN_RUNNING;
1629 waiting->waiting = NULL; 1640 waiting->waiting = NULL;
1630 pl08x_issue_pending(&waiting->chan); 1641 pl08x_issue_pending(&waiting->chan);