dmaengine: qcom_hidma: correct API violation for submit
authorSinan Kaya <okaya@codeaurora.org>
Fri, 30 Jun 2017 14:43:05 +0000 (10:43 -0400)
committerVinod Koul <vinod.koul@intel.com>
Mon, 3 Jul 2017 05:09:51 +0000 (10:39 +0530)
Current code is violating the DMA Engine API by putting the submitted
requests directly into the HW queue. This causes queued transactions
to be started by another thread as soon as the first one finishes.

The DMA Engine document clearly states this.

"dmaengine_submit() will not start the DMA operation".

Move HW queuing of the requests into the issue_pending() routine
to comply with API requirements also create a new queued state for
temporarily holding the requests.

A descriptor goes through these transitions now.

free->prepared->queued->active->completed->free

as opposed to

free->prepared->active->completed->free

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
drivers/dma/qcom/hidma.c
drivers/dma/qcom/hidma.h

index 84e3699a19bd90634f0f3efef11bba9fc65e8846..34fb6afd229b1c61812aa9ccc50b9e6df5a29f0b 100644 (file)
@@ -210,6 +210,7 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
        INIT_LIST_HEAD(&mchan->prepared);
        INIT_LIST_HEAD(&mchan->active);
        INIT_LIST_HEAD(&mchan->completed);
+       INIT_LIST_HEAD(&mchan->queued);
 
        spin_lock_init(&mchan->lock);
        list_add_tail(&mchan->chan.device_node, &ddev->channels);
@@ -230,9 +231,15 @@ static void hidma_issue_pending(struct dma_chan *dmach)
        struct hidma_chan *mchan = to_hidma_chan(dmach);
        struct hidma_dev *dmadev = mchan->dmadev;
        unsigned long flags;
+       struct hidma_desc *qdesc, *next;
        int status;
 
        spin_lock_irqsave(&mchan->lock, flags);
+       list_for_each_entry_safe(qdesc, next, &mchan->queued, node) {
+               hidma_ll_queue_request(dmadev->lldev, qdesc->tre_ch);
+               list_move_tail(&qdesc->node, &mchan->active);
+       }
+
        if (!mchan->running) {
                struct hidma_desc *desc = list_first_entry(&mchan->active,
                                                           struct hidma_desc,
@@ -315,17 +322,18 @@ static dma_cookie_t hidma_tx_submit(struct dma_async_tx_descriptor *txd)
                pm_runtime_put_autosuspend(dmadev->ddev.dev);
                return -ENODEV;
        }
+       pm_runtime_mark_last_busy(dmadev->ddev.dev);
+       pm_runtime_put_autosuspend(dmadev->ddev.dev);
 
        mdesc = container_of(txd, struct hidma_desc, desc);
        spin_lock_irqsave(&mchan->lock, irqflags);
 
-       /* Move descriptor to active */
-       list_move_tail(&mdesc->node, &mchan->active);
+       /* Move descriptor to queued */
+       list_move_tail(&mdesc->node, &mchan->queued);
 
        /* Update cookie */
        cookie = dma_cookie_assign(txd);
 
-       hidma_ll_queue_request(dmadev->lldev, mdesc->tre_ch);
        spin_unlock_irqrestore(&mchan->lock, irqflags);
 
        return cookie;
@@ -431,6 +439,7 @@ static int hidma_terminate_channel(struct dma_chan *chan)
        list_splice_init(&mchan->active, &list);
        list_splice_init(&mchan->prepared, &list);
        list_splice_init(&mchan->completed, &list);
+       list_splice_init(&mchan->queued, &list);
        spin_unlock_irqrestore(&mchan->lock, irqflags);
 
        /* this suspends the existing transfer */
index c7d014235c324e1652e1d7e4c0c5a5658c28ad10..41e0aa283828e2e50f2b424eee45225a2ee40181 100644 (file)
@@ -104,6 +104,7 @@ struct hidma_chan {
        struct dma_chan                 chan;
        struct list_head                free;
        struct list_head                prepared;
+       struct list_head                queued;
        struct list_head                active;
        struct list_head                completed;