mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-28 15:20:41 +00:00
dmaengine: Move all map_sg/unmap_sg for slave channel to its client
Dan Williams wrote: ... DMA-slave clients request specific channels and know the hardware details at a low level, so it should not be too high an expectation to push dma mapping responsibility to the client. Also this patch includes DMA_COMPL_{SRC,DEST}_UNMAP_SINGLE support for dw_dmac driver. Acked-by: Maciej Sosnowski <maciej.sosnowski@intel.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
bbea0b6e0d
commit
657a77fa72
3 changed files with 49 additions and 34 deletions
|
@ -253,25 +253,28 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
|
||||||
list_move(&desc->desc_node, &atchan->free_list);
|
list_move(&desc->desc_node, &atchan->free_list);
|
||||||
|
|
||||||
/* unmap dma addresses */
|
/* unmap dma addresses */
|
||||||
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
if (!atchan->chan_common.private) {
|
||||||
if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
|
struct device *parent = chan2parent(&atchan->chan_common);
|
||||||
dma_unmap_single(chan2parent(&atchan->chan_common),
|
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
||||||
desc->lli.daddr,
|
if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
|
||||||
desc->len, DMA_FROM_DEVICE);
|
dma_unmap_single(parent,
|
||||||
else
|
desc->lli.daddr,
|
||||||
dma_unmap_page(chan2parent(&atchan->chan_common),
|
desc->len, DMA_FROM_DEVICE);
|
||||||
desc->lli.daddr,
|
else
|
||||||
desc->len, DMA_FROM_DEVICE);
|
dma_unmap_page(parent,
|
||||||
}
|
desc->lli.daddr,
|
||||||
if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
desc->len, DMA_FROM_DEVICE);
|
||||||
if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
|
}
|
||||||
dma_unmap_single(chan2parent(&atchan->chan_common),
|
if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
||||||
desc->lli.saddr,
|
if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
|
||||||
desc->len, DMA_TO_DEVICE);
|
dma_unmap_single(parent,
|
||||||
else
|
desc->lli.saddr,
|
||||||
dma_unmap_page(chan2parent(&atchan->chan_common),
|
desc->len, DMA_TO_DEVICE);
|
||||||
desc->lli.saddr,
|
else
|
||||||
desc->len, DMA_TO_DEVICE);
|
dma_unmap_page(parent,
|
||||||
|
desc->lli.saddr,
|
||||||
|
desc->len, DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -647,8 +650,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||||
|
|
||||||
reg_width = atslave->reg_width;
|
reg_width = atslave->reg_width;
|
||||||
|
|
||||||
sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);
|
|
||||||
|
|
||||||
ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
|
ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
|
||||||
ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN;
|
ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN;
|
||||||
|
|
||||||
|
|
|
@ -212,16 +212,25 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
|
||||||
list_splice_init(&desc->tx_list, &dwc->free_list);
|
list_splice_init(&desc->tx_list, &dwc->free_list);
|
||||||
list_move(&desc->desc_node, &dwc->free_list);
|
list_move(&desc->desc_node, &dwc->free_list);
|
||||||
|
|
||||||
/*
|
if (!dwc->chan.private) {
|
||||||
* We use dma_unmap_page() regardless of how the buffers were
|
struct device *parent = chan2parent(&dwc->chan);
|
||||||
* mapped before they were submitted...
|
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
||||||
*/
|
if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
|
||||||
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))
|
dma_unmap_single(parent, desc->lli.dar,
|
||||||
dma_unmap_page(chan2parent(&dwc->chan), desc->lli.dar,
|
desc->len, DMA_FROM_DEVICE);
|
||||||
desc->len, DMA_FROM_DEVICE);
|
else
|
||||||
if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
|
dma_unmap_page(parent, desc->lli.dar,
|
||||||
dma_unmap_page(chan2parent(&dwc->chan), desc->lli.sar,
|
desc->len, DMA_FROM_DEVICE);
|
||||||
desc->len, DMA_TO_DEVICE);
|
}
|
||||||
|
if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
||||||
|
if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
|
||||||
|
dma_unmap_single(parent, desc->lli.sar,
|
||||||
|
desc->len, DMA_TO_DEVICE);
|
||||||
|
else
|
||||||
|
dma_unmap_page(parent, desc->lli.sar,
|
||||||
|
desc->len, DMA_TO_DEVICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The API requires that no submissions are done from a
|
* The API requires that no submissions are done from a
|
||||||
|
@ -658,8 +667,6 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||||
reg_width = dws->reg_width;
|
reg_width = dws->reg_width;
|
||||||
prev = first = NULL;
|
prev = first = NULL;
|
||||||
|
|
||||||
sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);
|
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case DMA_TO_DEVICE:
|
case DMA_TO_DEVICE:
|
||||||
ctllo = (DWC_DEFAULT_CTLLO
|
ctllo = (DWC_DEFAULT_CTLLO
|
||||||
|
|
|
@ -576,6 +576,7 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
enum dma_data_direction direction;
|
enum dma_data_direction direction;
|
||||||
|
unsigned int sglen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't do DMA on "complex" transfers, i.e. with
|
* We don't do DMA on "complex" transfers, i.e. with
|
||||||
|
@ -605,11 +606,14 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
|
||||||
else
|
else
|
||||||
direction = DMA_TO_DEVICE;
|
direction = DMA_TO_DEVICE;
|
||||||
|
|
||||||
|
sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction);
|
||||||
|
if (sglen != data->sg_len)
|
||||||
|
goto unmap_exit;
|
||||||
desc = chan->device->device_prep_slave_sg(chan,
|
desc = chan->device->device_prep_slave_sg(chan,
|
||||||
data->sg, data->sg_len, direction,
|
data->sg, data->sg_len, direction,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
if (!desc)
|
if (!desc)
|
||||||
return -ENOMEM;
|
goto unmap_exit;
|
||||||
|
|
||||||
host->dma.data_desc = desc;
|
host->dma.data_desc = desc;
|
||||||
desc->callback = atmci_dma_complete;
|
desc->callback = atmci_dma_complete;
|
||||||
|
@ -620,6 +624,9 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
|
||||||
chan->device->device_issue_pending(chan);
|
chan->device->device_issue_pending(chan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
unmap_exit:
|
||||||
|
dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_MMC_ATMELMCI_DMA */
|
#else /* CONFIG_MMC_ATMELMCI_DMA */
|
||||||
|
|
Loading…
Reference in a new issue