[PATCH 060/133] dma: pl330: Fix cyclic transfers
Kamal Mostafa
kamal at canonical.com
Wed Aug 21 19:40:51 UTC 2013
On Fri, 2013-08-16 at 15:33 -0700, Kamal Mostafa wrote:
> 3.8.13.7 -stable review patch. If anyone has any objections, please let me know.
Actually, I'm dropping this patch from 3.8-stable pending resolution of
the "flags parameter" bug found by Luis and Lars in this earlier stable@
thread:
> Subject: Patch "dma: pl330: Fix cyclic transfers" has been added
> to the 3.4-stable tree
> >
> > * function pl330_prep_dma_cyclic() signature doesn't contain the
> > 'flags' parameter introduced by commit
> > ec8b5e48c03790a68cb875fe5064007a9cbdfdd0
> >
> Hm, that's actually a bug in the original patch. spin_lock_irqsave()
> should
> not be using the flags parameter, but instead a variable placed on the
> stack. Things will still work by using the parameter, but it's not
> exactly
> how things are supposed to be done.
> - Lars
As Greg mentioned before, if someone wants to re-submit a fixed version
of this we'd take it for stable 3.4 through 3.8.
-Kamal
> ------------------
>
> From: Lars-Peter Clausen <lars at metafoo.de>
>
> commit fc51446021f42aca8906e701fc2292965aafcb15 upstream.
>
> Allocate a descriptor for each period of a cyclic transfer, not just the first.
> Also since the callback needs to be called for each finished period make sure to
> initialize the callback and callback_param fields of each descriptor in a cyclic
> transfer.
>
> Signed-off-by: Lars-Peter Clausen <lars at metafoo.de>
> Signed-off-by: Vinod Koul <vinod.koul at intel.com>
> Signed-off-by: Kamal Mostafa <kamal at canonical.com>
> ---
> drivers/dma/pl330.c | 93 ++++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 67 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 4bed3f1..9cfe424 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -2501,6 +2501,10 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
> /* Assign cookies to all nodes */
> while (!list_empty(&last->node)) {
> desc = list_entry(last->node.next, struct dma_pl330_desc, node);
> + if (pch->cyclic) {
> + desc->txd.callback = last->txd.callback;
> + desc->txd.callback_param = last->txd.callback_param;
> + }
>
> dma_cookie_assign(&desc->txd);
>
> @@ -2684,45 +2688,82 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
> size_t period_len, enum dma_transfer_direction direction,
> unsigned long flags, void *context)
> {
> - struct dma_pl330_desc *desc;
> + struct dma_pl330_desc *desc = NULL, *first = NULL;
> struct dma_pl330_chan *pch = to_pchan(chan);
> + struct dma_pl330_dmac *pdmac = pch->dmac;
> + unsigned int i;
> dma_addr_t dst;
> dma_addr_t src;
>
> - desc = pl330_get_desc(pch);
> - if (!desc) {
> - dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> - __func__, __LINE__);
> + if (len % period_len != 0)
> return NULL;
> - }
>
> - switch (direction) {
> - case DMA_MEM_TO_DEV:
> - desc->rqcfg.src_inc = 1;
> - desc->rqcfg.dst_inc = 0;
> - desc->req.rqtype = MEMTODEV;
> - src = dma_addr;
> - dst = pch->fifo_addr;
> - break;
> - case DMA_DEV_TO_MEM:
> - desc->rqcfg.src_inc = 0;
> - desc->rqcfg.dst_inc = 1;
> - desc->req.rqtype = DEVTOMEM;
> - src = pch->fifo_addr;
> - dst = dma_addr;
> - break;
> - default:
> + if (!is_slave_direction(direction)) {
> dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
> __func__, __LINE__);
> return NULL;
> }
>
> - desc->rqcfg.brst_size = pch->burst_sz;
> - desc->rqcfg.brst_len = 1;
> + for (i = 0; i < len / period_len; i++) {
> + desc = pl330_get_desc(pch);
> + if (!desc) {
> + dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> + __func__, __LINE__);
>
> - pch->cyclic = true;
> + if (!first)
> + return NULL;
> +
> + spin_lock_irqsave(&pdmac->pool_lock, flags);
> +
> + while (!list_empty(&first->node)) {
> + desc = list_entry(first->node.next,
> + struct dma_pl330_desc, node);
> + list_move_tail(&desc->node, &pdmac->desc_pool);
> + }
> +
> + list_move_tail(&first->node, &pdmac->desc_pool);
>
> - fill_px(&desc->px, dst, src, period_len);
> + spin_unlock_irqrestore(&pdmac->pool_lock, flags);
> +
> + return NULL;
> + }
> +
> + switch (direction) {
> + case DMA_MEM_TO_DEV:
> + desc->rqcfg.src_inc = 1;
> + desc->rqcfg.dst_inc = 0;
> + desc->req.rqtype = MEMTODEV;
> + src = dma_addr;
> + dst = pch->fifo_addr;
> + break;
> + case DMA_DEV_TO_MEM:
> + desc->rqcfg.src_inc = 0;
> + desc->rqcfg.dst_inc = 1;
> + desc->req.rqtype = DEVTOMEM;
> + src = pch->fifo_addr;
> + dst = dma_addr;
> + break;
> + default:
> + break;
> + }
> +
> + desc->rqcfg.brst_size = pch->burst_sz;
> + desc->rqcfg.brst_len = 1;
> + fill_px(&desc->px, dst, src, period_len);
> +
> + if (!first)
> + first = desc;
> + else
> + list_add_tail(&desc->node, &first->node);
> +
> + dma_addr += period_len;
> + }
> +
> + if (!desc)
> + return NULL;
> +
> + pch->cyclic = true;
> + desc->txd.flags = flags;
>
> return &desc->txd;
> }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20130821/7b04ddfa/attachment.sig>
More information about the kernel-team
mailing list