OSDN Git Service

dmaengine: pl330: _stop: clear interrupt status
authorSugar Zhang <sugar.zhang@rock-chips.com>
Wed, 3 Apr 2019 11:06:22 +0000 (19:06 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 31 May 2019 13:46:14 +0000 (06:46 -0700)
commit1d057fefa0459a18c414308a2612f73f9eb8d72a
treee9726abf1aa96186da864d0b6831fa5ff07406df
parentcadb16d9e0f35348ff9e336bf0a7892c534c755d
dmaengine: pl330: _stop: clear interrupt status

[ Upstream commit 2da254cc7908105a60a6bb219d18e8dced03dcb9 ]

This patch kill instructs the DMAC to immediately terminate
execution of a thread. and then clear the interrupt status,
at last, stop generating interrupts for DMA_SEV. to guarantee
the next dma start is clean. otherwise, one interrupt maybe leave
to next start and make some mistake.

we can reporduce the problem as follows:

DMASEV: modify the event-interrupt resource, and if the INTEN sets
function as interrupt, the DMAC will set irq<event_num> HIGH to
generate interrupt. write INTCLR to clear interrupt.

DMA EXECUTING INSTRUCTS DMA TERMINATE
| |
| |
       ...       _stop
| |
| spin_lock_irqsave
     DMASEV |
| |
|     mask INTEN
| |
|      DMAKILL
| |
| spin_unlock_irqrestore

in above case, a interrupt was left, and if we unmask INTEN, the DMAC
will set irq<event_num> HIGH to generate interrupt.

to fix this, do as follows:

DMA EXECUTING INSTRUCTS DMA TERMINATE
| |
| |
       ...       _stop
| |
| spin_lock_irqsave
     DMASEV |
| |
|      DMAKILL
| |
|    clear INTCLR
|     mask INTEN
| |
| spin_unlock_irqrestore

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/dma/pl330.c