Skip to content

Commit 8cda3ec

Browse files
ij-intelvinodkoul
authored andcommitted
dmaengine: pl330: Return DMA_PAUSED when transaction is paused
pl330_pause() does not set anything to indicate paused condition which causes pl330_tx_status() to return DMA_IN_PROGRESS. This breaks 8250 DMA flush after the fix in commit 57e9af7 ("serial: 8250_dma: Fix DMA Rx rearm race"). The function comment for pl330_pause() claims pause is supported but resume is not which is enough for 8250 DMA flush to work as long as DMA status reports DMA_PAUSED when appropriate. Add PAUSED state for descriptor and mark BUSY descriptors with PAUSED in pl330_pause(). Return DMA_PAUSED from pl330_tx_status() when the descriptor is PAUSED. Reported-by: Richard Tresidder <[email protected]> Tested-by: Richard Tresidder <[email protected]> Fixes: 88987d2 ("dmaengine: pl330: add DMA_PAUSE feature") Cc: [email protected] Link: https://lore.kernel.org/linux-serial/[email protected]/ Signed-off-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent e2dcbc3 commit 8cda3ec

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

drivers/dma/pl330.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,12 @@ enum desc_status {
403403
* of a channel can be BUSY at any time.
404404
*/
405405
BUSY,
406+
/*
407+
* Pause was called while descriptor was BUSY. Due to hardware
408+
* limitations, only termination is possible for descriptors
409+
* that have been paused.
410+
*/
411+
PAUSED,
406412
/*
407413
* Sitting on the channel work_list but xfer done
408414
* by PL330 core
@@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
20412047
list_for_each_entry(desc, &pch->work_list, node) {
20422048

20432049
/* If already submitted */
2044-
if (desc->status == BUSY)
2050+
if (desc->status == BUSY || desc->status == PAUSED)
20452051
continue;
20462052

20472053
ret = pl330_submit_req(pch->thread, desc);
@@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan)
23262332
{
23272333
struct dma_pl330_chan *pch = to_pchan(chan);
23282334
struct pl330_dmac *pl330 = pch->dmac;
2335+
struct dma_pl330_desc *desc;
23292336
unsigned long flags;
23302337

23312338
pm_runtime_get_sync(pl330->ddma.dev);
@@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan)
23352342
_stop(pch->thread);
23362343
spin_unlock(&pl330->lock);
23372344

2345+
list_for_each_entry(desc, &pch->work_list, node) {
2346+
if (desc->status == BUSY)
2347+
desc->status = PAUSED;
2348+
}
23382349
spin_unlock_irqrestore(&pch->lock, flags);
23392350
pm_runtime_mark_last_busy(pl330->ddma.dev);
23402351
pm_runtime_put_autosuspend(pl330->ddma.dev);
@@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
24252436
else if (running && desc == running)
24262437
transferred =
24272438
pl330_get_current_xferred_count(pch, desc);
2428-
else if (desc->status == BUSY)
2439+
else if (desc->status == BUSY || desc->status == PAUSED)
24292440
/*
24302441
* Busy but not running means either just enqueued,
24312442
* or finished and not yet marked done
@@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
24422453
case DONE:
24432454
ret = DMA_COMPLETE;
24442455
break;
2456+
case PAUSED:
2457+
ret = DMA_PAUSED;
2458+
break;
24452459
case PREP:
24462460
case BUSY:
24472461
ret = DMA_IN_PROGRESS;

0 commit comments

Comments
 (0)