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@xxxxxxxxxx> > > 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@xxxxxxxxxx> > Signed-off-by: Vinod Koul <vinod.koul@xxxxxxxxx> > Signed-off-by: Kamal Mostafa <kamal@xxxxxxxxxxxxx> > --- > 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; > }
Attachment:
signature.asc
Description: This is a digitally signed message part