diff options
-rw-r--r-- | drivers/dma/pl330.c | 15 |
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, | |||
2272 | { | 2272 | { |
2273 | enum dma_status ret; | 2273 | enum dma_status ret; |
2274 | unsigned long flags; | 2274 | unsigned long flags; |
2275 | struct dma_pl330_desc *desc, *running = NULL; | 2275 | struct dma_pl330_desc *desc, *running = NULL, *last_enq = NULL; |
2276 | struct dma_pl330_chan *pch = to_pchan(chan); | 2276 | struct dma_pl330_chan *pch = to_pchan(chan); |
2277 | unsigned int transferred, residual = 0; | 2277 | unsigned int transferred, residual = 0; |
2278 | 2278 | ||
@@ -2285,10 +2285,13 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
2285 | goto out; | 2285 | goto out; |
2286 | 2286 | ||
2287 | spin_lock_irqsave(&pch->lock, flags); | 2287 | spin_lock_irqsave(&pch->lock, flags); |
2288 | spin_lock(&pch->thread->dmac->lock); | ||
2288 | 2289 | ||
2289 | if (pch->thread->req_running != -1) | 2290 | if (pch->thread->req_running != -1) |
2290 | running = pch->thread->req[pch->thread->req_running].desc; | 2291 | running = pch->thread->req[pch->thread->req_running].desc; |
2291 | 2292 | ||
2293 | last_enq = pch->thread->req[pch->thread->lstenq].desc; | ||
2294 | |||
2292 | /* Check in pending list */ | 2295 | /* Check in pending list */ |
2293 | list_for_each_entry(desc, &pch->work_list, node) { | 2296 | list_for_each_entry(desc, &pch->work_list, node) { |
2294 | if (desc->status == DONE) | 2297 | if (desc->status == DONE) |
@@ -2296,6 +2299,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
2296 | else if (running && desc == running) | 2299 | else if (running && desc == running) |
2297 | transferred = | 2300 | transferred = |
2298 | pl330_get_current_xferred_count(pch, desc); | 2301 | pl330_get_current_xferred_count(pch, desc); |
2302 | else if (desc->status == BUSY) | ||
2303 | /* | ||
2304 | * Busy but not running means either just enqueued, | ||
2305 | * or finished and not yet marked done | ||
2306 | */ | ||
2307 | if (desc == last_enq) | ||
2308 | transferred = 0; | ||
2309 | else | ||
2310 | transferred = desc->bytes_requested; | ||
2299 | else | 2311 | else |
2300 | transferred = 0; | 2312 | transferred = 0; |
2301 | residual += desc->bytes_requested - transferred; | 2313 | residual += desc->bytes_requested - transferred; |
@@ -2316,6 +2328,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
2316 | if (desc->last) | 2328 | if (desc->last) |
2317 | residual = 0; | 2329 | residual = 0; |
2318 | } | 2330 | } |
2331 | spin_unlock(&pch->thread->dmac->lock); | ||
2319 | spin_unlock_irqrestore(&pch->lock, flags); | 2332 | spin_unlock_irqrestore(&pch->lock, flags); |
2320 | 2333 | ||
2321 | out: | 2334 | out: |