]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00292398 PXP: refine two spin locks usage in PXP dma driver
authorFancy Fang <B47543@freescale.com>
Tue, 17 Dec 2013 08:58:26 +0000 (16:58 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Mon, 16 Jun 2014 16:09:14 +0000 (18:09 +0200)
This patch provides the following refinements:
1. For pxp channel lock, use spin_lock() instead of spin_lock_irqsave().
   Since this lock is not used in any ISR. Moreover, this can increase the
   driver's concurrency with no local irq disabled.
2. Narrow down the pxp lock's locking range in pxp_issue_pending().
   Since this lock is also used in PXP ISR, so its hold time should be as
   few as possible to reduce the time when local irq disabled.

Signed-off-by: Fancy Fang <B47543@freescale.com>
drivers/dma/pxp/pxp_dma_v2.c

index 9102dd6abeabb4ec6d0c6b51744c5d0aab8a79e5..42f6f837707d8583b900954604a2ecbe8f667c8a 100644 (file)
@@ -1126,12 +1126,16 @@ static void pxpdma_dostart_work(struct pxps *pxp)
        spin_unlock_irqrestore(&pxp->lock, flags);
 }
 
-static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct list_head *list)
+static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
 {
+       unsigned long flags;
        struct pxp_tx_desc *desc = NULL;
+
        do {
                desc = pxpdma_first_queued(pxp_chan);
-               list_move_tail(&desc->list, list);
+               spin_lock_irqsave(&pxp->lock, flags);
+               list_move_tail(&desc->list, &head);
+               spin_unlock_irqrestore(&pxp->lock, flags);
        } while (!list_empty(&pxp_chan->queue));
 }
 
@@ -1140,12 +1144,11 @@ static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
        struct pxp_tx_desc *desc = to_tx_desc(tx);
        struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
        dma_cookie_t cookie;
-       unsigned long flags;
 
        dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
 
        /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
-       spin_lock_irqsave(&pxp_chan->lock, flags);
+       spin_lock(&pxp_chan->lock);
 
        cookie = pxp_chan->dma_chan.cookie;
 
@@ -1159,7 +1162,7 @@ static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
        /* Here we add the tx descriptor to our PxP task queue. */
        list_add_tail(&desc->list, &pxp_chan->queue);
 
-       spin_unlock_irqrestore(&pxp_chan->lock, flags);
+       spin_unlock(&pxp_chan->lock);
 
        dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
 
@@ -1337,21 +1340,18 @@ static void pxp_issue_pending(struct dma_chan *chan)
        struct pxp_channel *pxp_chan = to_pxp_channel(chan);
        struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
        struct pxps *pxp = to_pxp(pxp_dma);
-       unsigned long flags0, flags;
 
-       spin_lock_irqsave(&pxp->lock, flags0);
-       spin_lock_irqsave(&pxp_chan->lock, flags);
+       spin_lock(&pxp_chan->lock);
 
-       if (!list_empty(&pxp_chan->queue)) {
-               pxpdma_dequeue(pxp_chan, &head);
-               pxp_chan->status = PXP_CHANNEL_READY;
-       } else {
-               spin_unlock_irqrestore(&pxp_chan->lock, flags);
-               spin_unlock_irqrestore(&pxp->lock, flags0);
+       if (list_empty(&pxp_chan->queue)) {
+               spin_unlock(&pxp_chan->lock);
                return;
        }
-       spin_unlock_irqrestore(&pxp_chan->lock, flags);
-       spin_unlock_irqrestore(&pxp->lock, flags0);
+
+       pxpdma_dequeue(pxp_chan, pxp);
+       pxp_chan->status = PXP_CHANNEL_READY;
+
+       spin_unlock(&pxp_chan->lock);
 
        pxp_clk_enable(pxp);
        wake_up_interruptible(&pxp->thread_waitq);
@@ -1367,16 +1367,15 @@ static void __pxp_terminate_all(struct dma_chan *chan)
 static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                        unsigned long arg)
 {
-       unsigned long flags;
        struct pxp_channel *pxp_chan = to_pxp_channel(chan);
 
        /* Only supports DMA_TERMINATE_ALL */
        if (cmd != DMA_TERMINATE_ALL)
                return -ENXIO;
 
-       spin_lock_irqsave(&pxp_chan->lock, flags);
+       spin_lock(&pxp_chan->lock);
        __pxp_terminate_all(chan);
-       spin_unlock_irqrestore(&pxp_chan->lock, flags);
+       spin_unlock(&pxp_chan->lock);
 
        return 0;
 }
@@ -1412,16 +1411,15 @@ err_chan:
 
 static void pxp_free_chan_resources(struct dma_chan *chan)
 {
-       unsigned long flags;
        struct pxp_channel *pxp_chan = to_pxp_channel(chan);
 
-       spin_lock_irqsave(&pxp_chan->lock, flags);
+       spin_lock(&pxp_chan->lock);
 
        __pxp_terminate_all(chan);
 
        pxp_chan->status = PXP_CHANNEL_FREE;
 
-       spin_unlock_irqrestore(&pxp_chan->lock, flags);
+       spin_unlock(&pxp_chan->lock);
 }
 
 static enum dma_status pxp_tx_status(struct dma_chan *chan,