Re: [PATCH] dmaengine: Add support for MEMCPY for imx-dma.

From: Vinod Koul
Date: Fri Dec 23 2011 - 12:38:37 EST


On Fri, 2011-12-16 at 16:59 +0100, Javier Martin wrote:
> MEMCPY transfers allow DMA copies from memory to
> memory. This patch has been tested with dmatest
> device driver.
>
> Signed-off-by: Javier Martin <javier.martin@xxxxxxxxxxxxxxxxx>
> ---
> drivers/dma/imx-dma.c | 37 ++++++++++++++++++++++++++++++++++++-
> 1 files changed, 36 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
> index d99f71c..222cd7b 100644
> --- a/drivers/dma/imx-dma.c
> +++ b/drivers/dma/imx-dma.c
> @@ -196,7 +196,8 @@ static int imxdma_alloc_chan_resources(struct dma_chan *chan)
> struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
> struct imx_dma_data *data = chan->private;
>
> - imxdmac->dma_request = data->dma_request;
> + if (data != NULL)
> + imxdmac->dma_request = data->dma_request;
>
> dma_async_tx_descriptor_init(&imxdmac->desc, chan);
> imxdmac->desc.tx_submit = imxdma_tx_submit;
> @@ -328,6 +329,37 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
> return &imxdmac->desc;
> }
>
> +static struct dma_async_tx_descriptor *imxdma_prep_dma_memcpy(
> + struct dma_chan *chan, dma_addr_t dest,
> + dma_addr_t src, size_t len, unsigned long flags)
> +{
> + struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
> + struct imxdma_engine *imxdma = imxdmac->imxdma;
> + int ret;
> +
> + dev_dbg(imxdma->dev, "%s channel: %d src=0x%x dst=0x%x len=%d\n",
> + __func__, imxdmac->channel, src, dest, len);
> +
> + if (imxdmac->status == DMA_IN_PROGRESS)
> + return NULL;
> +
> + imxdmac->status = DMA_IN_PROGRESS;
why? prepare doesn't mean DMA is in progress. You can get multiple
descriptors for same channel by calling prepare multiple times.
Even one descriptor can be memcpy whereas other is slave...
In issue_pending this should be moved to DMA_IN_PROGRESS
> +
> + ret = imx_dma_config_channel(imxdmac->imxdma_channel,
> + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
> + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
> + 0, 0);
> + if (ret)
> + return NULL;
> +
> + ret = imx_dma_setup_single(imxdmac->imxdma_channel, src, len,
> + dest, DMA_MODE_WRITE);
> + if (ret)
> + return NULL;
> +
> + return &imxdmac->desc;
> +}
> +
> static void imxdma_issue_pending(struct dma_chan *chan)
> {
> /*
> @@ -348,6 +380,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
>
> dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask);
> dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask);
> + dma_cap_set(DMA_MEMCPY, imxdma->dma_device.cap_mask);
>
> /* Initialize channel parameters */
> for (i = 0; i < MAX_DMA_CHANNELS; i++) {
> @@ -381,11 +414,13 @@ static int __init imxdma_probe(struct platform_device *pdev)
> imxdma->dma_device.device_tx_status = imxdma_tx_status;
> imxdma->dma_device.device_prep_slave_sg = imxdma_prep_slave_sg;
> imxdma->dma_device.device_prep_dma_cyclic = imxdma_prep_dma_cyclic;
> + imxdma->dma_device.device_prep_dma_memcpy = imxdma_prep_dma_memcpy;
> imxdma->dma_device.device_control = imxdma_control;
> imxdma->dma_device.device_issue_pending = imxdma_issue_pending;
>
> platform_set_drvdata(pdev, imxdma);
>
> + imxdma->dma_device.copy_align = 2; /* 2^2 = 4 bytes alignment */
> imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms;
> dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff);
>


--
~Vinod

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/