dmaengine: dw-axi-dmac: Fix a non-atomic update #6044
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
dw_axi_dma_interrupt disables interrupts for the duration of the channel handling. It does so by clearing a bit in the DMA_CFG register - an action that involves a read-modify-write. That in itself would be safe because there will be no further interrupts, hence no reentrancy, were it the only bit of code accessing that register.
The only neighbour of INT_EN is DMAC_EN - the main enable for the block. That's not the sort of thing you would expect to be modified during the normal course of operation, but bizarrely it is set at the start of the transfer of every block, in axi_chan_block_xfer_star, by a call to axi_dma_enable. This can lead to INT_EN being accidentally cleared, which causes all DMA transfers to time out.
One might think that the enabling was being delayed until the first transfer, but the probe function calls axi_dma_resume which in turn calls axi_dma_enable, so that isn't the case.
Fix the atomicity problem by removing the spurious call to axi_dma_enable.
See: #6020, #5858, #5865