aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/pl330.c
diff options
context:
space:
mode:
authorVinod Koul <vinod.koul@intel.com>2016-10-03 09:19:03 +0530
committerVinod Koul <vinod.koul@intel.com>2016-10-03 09:19:03 +0530
commit709c9464c335e1f8e22ee108def77d53330a95c7 (patch)
tree505ba0ff73a90b537bd11a1aaa2aeba07100a49f /drivers/dma/pl330.c
parentMerge branch 'topic/omap' into for-linus (diff)
parentdmaengine: pl330: Acquire dmac's spinlock in pl330_tx_status (diff)
downloadlinux-dev-709c9464c335e1f8e22ee108def77d53330a95c7.tar.xz
linux-dev-709c9464c335e1f8e22ee108def77d53330a95c7.zip
Merge branch 'topic/pl330' into for-linus
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r--drivers/dma/pl330.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 1ecd4674aa23..030fe05ed43b 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2272,7 +2272,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
{
enum dma_status ret;
unsigned long flags;
- struct dma_pl330_desc *desc, *running = NULL;
+ struct dma_pl330_desc *desc, *running = NULL, *last_enq = NULL;
struct dma_pl330_chan *pch = to_pchan(chan);
unsigned int transferred, residual = 0;
@@ -2285,10 +2285,13 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
goto out;
spin_lock_irqsave(&pch->lock, flags);
+ spin_lock(&pch->thread->dmac->lock);
if (pch->thread->req_running != -1)
running = pch->thread->req[pch->thread->req_running].desc;
+ last_enq = pch->thread->req[pch->thread->lstenq].desc;
+
/* Check in pending list */
list_for_each_entry(desc, &pch->work_list, node) {
if (desc->status == DONE)
@@ -2296,6 +2299,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
else if (running && desc == running)
transferred =
pl330_get_current_xferred_count(pch, desc);
+ else if (desc->status == BUSY)
+ /*
+ * Busy but not running means either just enqueued,
+ * or finished and not yet marked done
+ */
+ if (desc == last_enq)
+ transferred = 0;
+ else
+ transferred = desc->bytes_requested;
else
transferred = 0;
residual += desc->bytes_requested - transferred;
@@ -2316,6 +2328,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
if (desc->last)
residual = 0;
}
+ spin_unlock(&pch->thread->dmac->lock);
spin_unlock_irqrestore(&pch->lock, flags);
out: