dmaengine: add DMA_COMPL_SKIP_{SRC,DEST}_UNMAP flags to control dma unmap
In some cases client code may need the dma-driver to skip the unmap of source and/or destination buffers. Setting these flags indicates to the driver to skip the unmap step. In this regard async_xor is currently broken in that it allows the destination buffer to be unmapped while an operation is still in progress, i.e. when the number of sources exceeds the hardware channel's maximum (fixed in a subsequent patch). Acked-by: Saeed Bishara <saeed@marvell.com> Acked-by: Maciej Sosnowski <maciej.sosnowski@intel.com> Acked-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
848c536a37
commit
e1d181efb1
|
@ -757,6 +757,27 @@ static void ioat_dma_cleanup_tasklet(unsigned long data)
|
||||||
chan->reg_base + IOAT_CHANCTRL_OFFSET);
|
chan->reg_base + IOAT_CHANCTRL_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* yes we are unmapping both _page and _single
|
||||||
|
* alloc'd regions with unmap_page. Is this
|
||||||
|
* *really* that bad?
|
||||||
|
*/
|
||||||
|
if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP))
|
||||||
|
pci_unmap_page(ioat_chan->device->pdev,
|
||||||
|
pci_unmap_addr(desc, dst),
|
||||||
|
pci_unmap_len(desc, len),
|
||||||
|
PCI_DMA_FROMDEVICE);
|
||||||
|
|
||||||
|
if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP))
|
||||||
|
pci_unmap_page(ioat_chan->device->pdev,
|
||||||
|
pci_unmap_addr(desc, src),
|
||||||
|
pci_unmap_len(desc, len),
|
||||||
|
PCI_DMA_TODEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ioat_dma_memcpy_cleanup - cleanup up finished descriptors
|
* ioat_dma_memcpy_cleanup - cleanup up finished descriptors
|
||||||
* @chan: ioat channel to be cleaned up
|
* @chan: ioat channel to be cleaned up
|
||||||
|
@ -817,21 +838,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
|
||||||
*/
|
*/
|
||||||
if (desc->async_tx.cookie) {
|
if (desc->async_tx.cookie) {
|
||||||
cookie = desc->async_tx.cookie;
|
cookie = desc->async_tx.cookie;
|
||||||
|
ioat_dma_unmap(ioat_chan, desc);
|
||||||
/*
|
|
||||||
* yes we are unmapping both _page and _single
|
|
||||||
* alloc'd regions with unmap_page. Is this
|
|
||||||
* *really* that bad?
|
|
||||||
*/
|
|
||||||
pci_unmap_page(ioat_chan->device->pdev,
|
|
||||||
pci_unmap_addr(desc, dst),
|
|
||||||
pci_unmap_len(desc, len),
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
pci_unmap_page(ioat_chan->device->pdev,
|
|
||||||
pci_unmap_addr(desc, src),
|
|
||||||
pci_unmap_len(desc, len),
|
|
||||||
PCI_DMA_TODEVICE);
|
|
||||||
|
|
||||||
if (desc->async_tx.callback) {
|
if (desc->async_tx.callback) {
|
||||||
desc->async_tx.callback(desc->async_tx.callback_param);
|
desc->async_tx.callback(desc->async_tx.callback_param);
|
||||||
desc->async_tx.callback = NULL;
|
desc->async_tx.callback = NULL;
|
||||||
|
@ -890,16 +897,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
|
||||||
if (desc->async_tx.cookie) {
|
if (desc->async_tx.cookie) {
|
||||||
cookie = desc->async_tx.cookie;
|
cookie = desc->async_tx.cookie;
|
||||||
desc->async_tx.cookie = 0;
|
desc->async_tx.cookie = 0;
|
||||||
|
ioat_dma_unmap(ioat_chan, desc);
|
||||||
pci_unmap_page(ioat_chan->device->pdev,
|
|
||||||
pci_unmap_addr(desc, dst),
|
|
||||||
pci_unmap_len(desc, len),
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
pci_unmap_page(ioat_chan->device->pdev,
|
|
||||||
pci_unmap_addr(desc, src),
|
|
||||||
pci_unmap_len(desc, len),
|
|
||||||
PCI_DMA_TODEVICE);
|
|
||||||
|
|
||||||
if (desc->async_tx.callback) {
|
if (desc->async_tx.callback) {
|
||||||
desc->async_tx.callback(desc->async_tx.callback_param);
|
desc->async_tx.callback(desc->async_tx.callback_param);
|
||||||
desc->async_tx.callback = NULL;
|
desc->async_tx.callback = NULL;
|
||||||
|
|
|
@ -82,11 +82,17 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
|
||||||
struct device *dev =
|
struct device *dev =
|
||||||
&iop_chan->device->pdev->dev;
|
&iop_chan->device->pdev->dev;
|
||||||
u32 len = unmap->unmap_len;
|
u32 len = unmap->unmap_len;
|
||||||
u32 src_cnt = unmap->unmap_src_cnt;
|
enum dma_ctrl_flags flags = desc->async_tx.flags;
|
||||||
dma_addr_t addr = iop_desc_get_dest_addr(unmap,
|
u32 src_cnt;
|
||||||
iop_chan);
|
dma_addr_t addr;
|
||||||
|
|
||||||
|
if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
||||||
|
addr = iop_desc_get_dest_addr(unmap, iop_chan);
|
||||||
dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
|
dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
||||||
|
src_cnt = unmap->unmap_src_cnt;
|
||||||
while (src_cnt--) {
|
while (src_cnt--) {
|
||||||
addr = iop_desc_get_src_addr(unmap,
|
addr = iop_desc_get_src_addr(unmap,
|
||||||
iop_chan,
|
iop_chan,
|
||||||
|
@ -94,6 +100,7 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
|
||||||
dma_unmap_page(dev, addr, len,
|
dma_unmap_page(dev, addr, len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
desc->group_head = NULL;
|
desc->group_head = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,13 +308,23 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
|
||||||
struct device *dev =
|
struct device *dev =
|
||||||
&mv_chan->device->pdev->dev;
|
&mv_chan->device->pdev->dev;
|
||||||
u32 len = unmap->unmap_len;
|
u32 len = unmap->unmap_len;
|
||||||
u32 src_cnt = unmap->unmap_src_cnt;
|
enum dma_ctrl_flags flags = desc->async_tx.flags;
|
||||||
dma_addr_t addr = mv_desc_get_dest_addr(unmap);
|
u32 src_cnt;
|
||||||
|
dma_addr_t addr;
|
||||||
|
|
||||||
|
if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
||||||
|
addr = mv_desc_get_dest_addr(unmap);
|
||||||
dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
|
dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
||||||
|
src_cnt = unmap->unmap_src_cnt;
|
||||||
while (src_cnt--) {
|
while (src_cnt--) {
|
||||||
addr = mv_desc_get_src_addr(unmap, src_cnt);
|
addr = mv_desc_get_src_addr(unmap,
|
||||||
dma_unmap_page(dev, addr, len, DMA_TO_DEVICE);
|
src_cnt);
|
||||||
|
dma_unmap_page(dev, addr, len,
|
||||||
|
DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
desc->group_head = NULL;
|
desc->group_head = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,10 +102,14 @@ enum dma_transaction_type {
|
||||||
* @DMA_CTRL_ACK - the descriptor cannot be reused until the client
|
* @DMA_CTRL_ACK - the descriptor cannot be reused until the client
|
||||||
* acknowledges receipt, i.e. has has a chance to establish any
|
* acknowledges receipt, i.e. has has a chance to establish any
|
||||||
* dependency chains
|
* dependency chains
|
||||||
|
* @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
|
||||||
|
* @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)
|
||||||
*/
|
*/
|
||||||
enum dma_ctrl_flags {
|
enum dma_ctrl_flags {
|
||||||
DMA_PREP_INTERRUPT = (1 << 0),
|
DMA_PREP_INTERRUPT = (1 << 0),
|
||||||
DMA_CTRL_ACK = (1 << 1),
|
DMA_CTRL_ACK = (1 << 1),
|
||||||
|
DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2),
|
||||||
|
DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue