diff options
author | Russell King - ARM Linux <linux@arm.linux.org.uk> | 2011-01-03 17:44:16 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-01-04 22:16:14 -0500 |
commit | 3d992e1a6f8465db3921ef75bfc490fbd2f40cd3 (patch) | |
tree | 4d7935045ef1654777754360f319c093f5f041e8 /drivers/dma/amba-pl08x.c | |
parent | c04287948ec8308fceedda980373bc7d53620255 (diff) |
ARM: PL08x: implement unmapping of memcpy buffers
The DMA engine API requires DMA engine implementations to unmap buffers
passed into the non-slave DMA methods unless the relevant completion
flag is set. We aren't doing this, so implement this facility.
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/amba-pl08x.c')
-rw-r--r-- | drivers/dma/amba-pl08x.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 00058e30a9c3..fb469dedcdf3 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c | |||
@@ -1527,13 +1527,33 @@ static void pl08x_ensure_on(struct pl08x_driver_data *pl08x) | |||
1527 | writel(val, pl08x->base + PL080_CONFIG); | 1527 | writel(val, pl08x->base + PL080_CONFIG); |
1528 | } | 1528 | } |
1529 | 1529 | ||
1530 | static void pl08x_unmap_buffers(struct pl08x_txd *txd) | ||
1531 | { | ||
1532 | struct device *dev = txd->tx.chan->device->dev; | ||
1533 | |||
1534 | if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | ||
1535 | if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE) | ||
1536 | dma_unmap_single(dev, txd->src_addr, txd->len, | ||
1537 | DMA_TO_DEVICE); | ||
1538 | else | ||
1539 | dma_unmap_page(dev, txd->src_addr, txd->len, | ||
1540 | DMA_TO_DEVICE); | ||
1541 | } | ||
1542 | if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | ||
1543 | if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE) | ||
1544 | dma_unmap_single(dev, txd->dst_addr, txd->len, | ||
1545 | DMA_FROM_DEVICE); | ||
1546 | else | ||
1547 | dma_unmap_page(dev, txd->dst_addr, txd->len, | ||
1548 | DMA_FROM_DEVICE); | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1530 | static void pl08x_tasklet(unsigned long data) | 1552 | static void pl08x_tasklet(unsigned long data) |
1531 | { | 1553 | { |
1532 | struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data; | 1554 | struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data; |
1533 | struct pl08x_driver_data *pl08x = plchan->host; | 1555 | struct pl08x_driver_data *pl08x = plchan->host; |
1534 | struct pl08x_txd *txd; | 1556 | struct pl08x_txd *txd; |
1535 | dma_async_tx_callback callback = NULL; | ||
1536 | void *callback_param = NULL; | ||
1537 | unsigned long flags; | 1557 | unsigned long flags; |
1538 | 1558 | ||
1539 | spin_lock_irqsave(&plchan->lock, flags); | 1559 | spin_lock_irqsave(&plchan->lock, flags); |
@@ -1542,18 +1562,10 @@ static void pl08x_tasklet(unsigned long data) | |||
1542 | plchan->at = NULL; | 1562 | plchan->at = NULL; |
1543 | 1563 | ||
1544 | if (txd) { | 1564 | if (txd) { |
1545 | callback = txd->tx.callback; | ||
1546 | callback_param = txd->tx.callback_param; | ||
1547 | |||
1548 | /* | 1565 | /* |
1549 | * Update last completed | 1566 | * Update last completed |
1550 | */ | 1567 | */ |
1551 | plchan->lc = txd->tx.cookie; | 1568 | plchan->lc = txd->tx.cookie; |
1552 | |||
1553 | /* | ||
1554 | * Free the descriptor | ||
1555 | */ | ||
1556 | pl08x_free_txd(pl08x, txd); | ||
1557 | } | 1569 | } |
1558 | /* | 1570 | /* |
1559 | * If a new descriptor is queued, set it up | 1571 | * If a new descriptor is queued, set it up |
@@ -1605,9 +1617,23 @@ static void pl08x_tasklet(unsigned long data) | |||
1605 | 1617 | ||
1606 | spin_unlock_irqrestore(&plchan->lock, flags); | 1618 | spin_unlock_irqrestore(&plchan->lock, flags); |
1607 | 1619 | ||
1608 | /* Callback to signal completion */ | 1620 | if (txd) { |
1609 | if (callback) | 1621 | dma_async_tx_callback callback = txd->tx.callback; |
1610 | callback(callback_param); | 1622 | void *callback_param = txd->tx.callback_param; |
1623 | |||
1624 | /* Don't try to unmap buffers on slave channels */ | ||
1625 | if (!plchan->slave) | ||
1626 | pl08x_unmap_buffers(txd); | ||
1627 | |||
1628 | /* Free the descriptor */ | ||
1629 | spin_lock_irqsave(&plchan->lock, flags); | ||
1630 | pl08x_free_txd(pl08x, txd); | ||
1631 | spin_unlock_irqrestore(&plchan->lock, flags); | ||
1632 | |||
1633 | /* Callback to signal completion */ | ||
1634 | if (callback) | ||
1635 | callback(callback_param); | ||
1636 | } | ||
1611 | } | 1637 | } |
1612 | 1638 | ||
1613 | static irqreturn_t pl08x_irq(int irq, void *dev) | 1639 | static irqreturn_t pl08x_irq(int irq, void *dev) |