From eab82533c972bf932434b69bbb71c6724d863ef7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 25 May 2012 12:32:00 +0100 Subject: dmaengine: PL08x: re-jig the starting of txds Rather than code the de-queue of the txd several times, move that into the start_txd function. Rename this to better illustrate what it's now doing, and call this function when starting a delayed memcpy(). Acked-by: Linus Walleij Tested-by: Linus Walleij Signed-off-by: Russell King --- drivers/dma/amba-pl08x.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers/dma/amba-pl08x.c') diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 88661fa4542c..c278d23adee7 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -354,20 +354,25 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch) * been set when the LLIs were constructed. Poke them into the hardware * and start the transfer. */ -static void pl08x_start_txd(struct pl08x_dma_chan *plchan, - struct pl08x_txd *txd) +static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan) { struct pl08x_driver_data *pl08x = plchan->host; struct pl08x_phy_chan *phychan = plchan->phychan; - struct pl08x_lli *lli = &txd->llis_va[0]; + struct pl08x_lli *lli; + struct pl08x_txd *txd; u32 val; + txd = list_first_entry(&plchan->pend_list, struct pl08x_txd, node); + list_del(&txd->node); + plchan->at = txd; /* Wait for channel inactive */ while (pl08x_phy_channel_busy(phychan)) cpu_relax(); + lli = &txd->llis_va[0]; + dev_vdbg(&pl08x->adev->dev, "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, " "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n", @@ -1272,15 +1277,8 @@ static void pl08x_issue_pending(struct dma_chan *chan) /* Take the first element in the queue and execute it */ if (!list_empty(&plchan->pend_list)) { - struct pl08x_txd *next; - - next = list_first_entry(&plchan->pend_list, - struct pl08x_txd, - node); - list_del(&next->node); plchan->state = PL08X_CHAN_RUNNING; - - pl08x_start_txd(plchan, next); + pl08x_start_next_txd(plchan); } spin_unlock_irqrestore(&plchan->lock, flags); @@ -1661,14 +1659,7 @@ static void pl08x_tasklet(unsigned long data) /* If a new descriptor is queued, set it up plchan->at is NULL here */ if (!list_empty(&plchan->pend_list)) { - struct pl08x_txd *next; - - next = list_first_entry(&plchan->pend_list, - struct pl08x_txd, - node); - list_del(&next->node); - - pl08x_start_txd(plchan, next); + pl08x_start_next_txd(plchan); } else if (plchan->phychan_hold) { /* * This channel is still in use - we have a new txd being @@ -1700,7 +1691,13 @@ static void pl08x_tasklet(unsigned long data) BUG_ON(ret); waiting->phychan_hold--; waiting->state = PL08X_CHAN_RUNNING; - pl08x_issue_pending(&waiting->chan); + /* + * Eww. We know this isn't going to deadlock + * but lockdep probably doens't. + */ + spin_lock(&waiting->lock); + pl08x_start_next_txd(waiting); + spin_unlock(&waiting->lock); break; } } -- cgit v1.2.3