|
@@ -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:
|