diff options
author | Russell King - ARM Linux <linux@arm.linux.org.uk> | 2011-01-03 17:45:17 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-01-04 22:16:14 -0500 |
commit | 8087aacda040bdbf84940712d132ce80c30b9d5d (patch) | |
tree | 3a59272bc4555eae854a012940a36f80a8f4c1a5 /drivers/dma | |
parent | 501e67e82dee68d0a594ec0549f3d6a2943c91f5 (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.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 650e2bbc7aad..bf6f7d02c9f6 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); |