aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Barber <smbarber@chromium.org>2016-08-18 20:59:59 -0400
committerVinod Koul <vinod.koul@intel.com>2016-09-09 07:49:09 -0400
commitd64e9a2c750930272492952c16f3f2c95311a6c9 (patch)
tree4238e4f37611bff089e9254004698568527a35ca
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
dmaengine: pl330: fix residual for non-running BUSY descriptors
Only one descriptor in the work list should be running at any given time, but it's possible to have an enqueued BUSY descriptor that has not yet transferred any data, or for a BUSY descriptor to linger briefly before transitioning to DONE. These cases should be handled to keep residual calculations consistent even with the non-running BUSY descriptors in the work list. Signed-off-by: Stephen Barber <smbarber@chromium.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/pl330.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 4fc3ffbd5ca0..31e9c49e5604 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2274,7 +2274,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2274{ 2274{
2275 enum dma_status ret; 2275 enum dma_status ret;
2276 unsigned long flags; 2276 unsigned long flags;
2277 struct dma_pl330_desc *desc, *running = NULL; 2277 struct dma_pl330_desc *desc, *running = NULL, *last_enq = NULL;
2278 struct dma_pl330_chan *pch = to_pchan(chan); 2278 struct dma_pl330_chan *pch = to_pchan(chan);
2279 unsigned int transferred, residual = 0; 2279 unsigned int transferred, residual = 0;
2280 2280
@@ -2291,6 +2291,8 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2291 if (pch->thread->req_running != -1) 2291 if (pch->thread->req_running != -1)
2292 running = pch->thread->req[pch->thread->req_running].desc; 2292 running = pch->thread->req[pch->thread->req_running].desc;
2293 2293
2294 last_enq = pch->thread->req[pch->thread->lstenq].desc;
2295
2294 /* Check in pending list */ 2296 /* Check in pending list */
2295 list_for_each_entry(desc, &pch->work_list, node) { 2297 list_for_each_entry(desc, &pch->work_list, node) {
2296 if (desc->status == DONE) 2298 if (desc->status == DONE)
@@ -2298,6 +2300,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2298 else if (running && desc == running) 2300 else if (running && desc == running)
2299 transferred = 2301 transferred =
2300 pl330_get_current_xferred_count(pch, desc); 2302 pl330_get_current_xferred_count(pch, desc);
2303 else if (desc->status == BUSY)
2304 /*
2305 * Busy but not running means either just enqueued,
2306 * or finished and not yet marked done
2307 */
2308 if (desc == last_enq)
2309 transferred = 0;
2310 else
2311 transferred = desc->bytes_requested;
2301 else 2312 else
2302 transferred = 0; 2313 transferred = 0;
2303 residual += desc->bytes_requested - transferred; 2314 residual += desc->bytes_requested - transferred;