Commit 8390318c authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Vinod Koul

dmaengine: ti: k3-udma: Fix terminated transfer handling

When we receive back the descriptor of the terminated transfer the cookie
must be marked as completed to make sure that the accounting is correct.

In udma_tx_status() the status should be marked as completed if the channel
is no longer running (it can only happen if the channel is not yet started
for the first time, or after a channel termination).

Fixes: 25dcb5dd ("dmaengine: ti: New driver for K3 UDMA")
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/20200214091441.27535-7-peter.ujfalusi@ti.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent c7450bb2
...@@ -1097,29 +1097,27 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data) ...@@ -1097,29 +1097,27 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data)
goto out; goto out;
} }
if (uc->cyclic) {
/* push the descriptor back to the ring */
if (d == uc->desc) { if (d == uc->desc) {
/* active descriptor */
if (uc->cyclic) {
udma_cyclic_packet_elapsed(uc); udma_cyclic_packet_elapsed(uc);
vchan_cyclic_callback(&d->vd); vchan_cyclic_callback(&d->vd);
}
} else { } else {
bool desc_done = false; if (udma_is_desc_really_done(uc, d)) {
if (d == uc->desc) {
desc_done = udma_is_desc_really_done(uc, d);
if (desc_done) {
uc->bcnt += d->residue; uc->bcnt += d->residue;
udma_start(uc); udma_start(uc);
vchan_cookie_complete(&d->vd);
} else { } else {
schedule_delayed_work(&uc->tx_drain.work, schedule_delayed_work(&uc->tx_drain.work,
0); 0);
} }
} }
} else {
if (desc_done) /*
vchan_cookie_complete(&d->vd); * terminated descriptor, mark the descriptor as
* completed to update the channel's cookie marker
*/
dma_cookie_complete(&d->vd.tx);
} }
} }
out: out:
...@@ -2769,6 +2767,9 @@ static enum dma_status udma_tx_status(struct dma_chan *chan, ...@@ -2769,6 +2767,9 @@ static enum dma_status udma_tx_status(struct dma_chan *chan,
ret = dma_cookie_status(chan, cookie, txstate); ret = dma_cookie_status(chan, cookie, txstate);
if (!udma_is_chan_running(uc))
ret = DMA_COMPLETE;
if (ret == DMA_IN_PROGRESS && udma_is_chan_paused(uc)) if (ret == DMA_IN_PROGRESS && udma_is_chan_paused(uc))
ret = DMA_PAUSED; ret = DMA_PAUSED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment