Commit 158769a5 authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Greg Kroah-Hartman

dmaengine: pl330: Fix hang on dmaengine_terminate_all on certain boards

commit 81cc6edc upstream.

The pl330 device could hang infinitely on certain boards when DMA
channels are terminated.

It was caused by lack of runtime resume when executing
pl330_terminate_all() which calls the _stop() function. _stop() accesses
device register and can loop infinitely while checking for device state.

The hang was confirmed by Dinh Nguyen on Altera SOCFPGA Cyclone V
board during boot. It can be also triggered with:

$ echo 1 > /sys/module/dmatest/parameters/iterations
$ echo dma1chan0 > /sys/module/dmatest/parameters/channel
$ echo 1 > /sys/module/dmatest/parameters/run
$ sleep 1
$ cat /sys/module/dmatest/parameters/run
Reported-by: default avatarDinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Fixes: ae43b328 ("ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12")
Tested-by: default avatarDinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0e20a595
...@@ -2127,6 +2127,7 @@ static int pl330_terminate_all(struct dma_chan *chan) ...@@ -2127,6 +2127,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
struct pl330_dmac *pl330 = pch->dmac; struct pl330_dmac *pl330 = pch->dmac;
LIST_HEAD(list); LIST_HEAD(list);
pm_runtime_get_sync(pl330->ddma.dev);
spin_lock_irqsave(&pch->lock, flags); spin_lock_irqsave(&pch->lock, flags);
spin_lock(&pl330->lock); spin_lock(&pl330->lock);
_stop(pch->thread); _stop(pch->thread);
...@@ -2151,6 +2152,8 @@ static int pl330_terminate_all(struct dma_chan *chan) ...@@ -2151,6 +2152,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
list_splice_tail_init(&pch->work_list, &pl330->desc_pool); list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool); list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
spin_unlock_irqrestore(&pch->lock, flags); spin_unlock_irqrestore(&pch->lock, flags);
pm_runtime_mark_last_busy(pl330->ddma.dev);
pm_runtime_put_autosuspend(pl330->ddma.dev);
return 0; return 0;
} }
......
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