diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-20 10:45:22 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-20 10:45:22 -0700 |
| commit | a10a019dd4c7c57bef6b8dda962c8881ad220af2 (patch) | |
| tree | c4eb799cc42f73f3efa4bca8328a02ffde94be94 /drivers/dma/xilinx | |
| parent | 60ee24f055f87c74d3fccdedcb761df9253fd5c0 (diff) | |
| parent | 075bc7b1d3dde5ed43fbaabbc1a69f09b7fc3a47 (diff) | |
| download | linux-stable-a10a019dd4c7c57bef6b8dda962c8881ad220af2.tar.gz linux-stable-a10a019dd4c7c57bef6b8dda962c8881ad220af2.zip | |
Merge tag 'dmaengine-fix-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine fixes from Vinod Koul:
- A couple of fixes in core around dma_chan_put() for kref underflow,
use-after-free and waiting for rcu readers for dma devices
- mmp sg length and wrong extended DRCMR base for SpacemiT K3
- hardware buffer descriptor chain fix for xilinx dma
- sun6i fixes for status behaviour and dma position registers
- runtime pm reference leak fix for sprd driver
* tag 'dmaengine-fix-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine:
dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg()
dmaengine: xilinx_dma: Fix hardware buffer descriptor chain after cyclic DMA
dmaengine: pxa: fix double counting of the hw descriptors
dmaengine: sun6i: fix undefined behaviour in sun6i_dma_tx_status
dmaengine: sun6i: fix non-atomic read of DMA position registers
dmaengine: xilinx_dma: Fix hardware buffer descriptor reuse order
dmaengine: wait for RCU readers before releasing dma_device
dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel()
dmaengine: Fix device kref underflow in dma_chan_put()
dmaengine: add dma_device_get() helper
dmaengine: sprd: Fix runtime PM reference leak in probe
dmaengine: ti: k3-udma-glue: fix NULL dereference in k3_udma_glue_release_rx_chn()
dmaengine: mmp_pdma: fix wrong extended DRCMR base for SpacemiT K3
Diffstat (limited to 'drivers/dma/xilinx')
| -rw-r--r-- | drivers/dma/xilinx/xilinx_dma.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index bef2b031d..cffe7c6fa 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -756,15 +756,25 @@ xilinx_aximcdma_alloc_tx_segment(struct xilinx_dma_chan *chan) return segment; } -static void xilinx_dma_clean_hw_desc(struct xilinx_axidma_desc_hw *hw) +static void xilinx_dma_clean_hw_desc(struct xilinx_dma_chan *chan, + struct xilinx_axidma_tx_segment *segment) { - u32 next_desc = hw->next_desc; - u32 next_desc_msb = hw->next_desc_msb; + dma_addr_t next; + u32 i; - memset(hw, 0, sizeof(struct xilinx_axidma_desc_hw)); + /* + * Restore the buffer descriptor's next descriptor pointer to the value + * set up in xilinx_dma_alloc_chan_resources(). Otherwise using the DMA + * in cyclic mode leaves the next descriptor pointer altered and + * prevents subsequent non-cyclic transfers. + */ + i = segment - chan->seg_v; + next = chan->seg_p + + sizeof(*chan->seg_v) * ((i + 1) % XILINX_DMA_NUM_DESCS); - hw->next_desc = next_desc; - hw->next_desc_msb = next_desc_msb; + memset(&segment->hw, 0, sizeof(segment->hw)); + segment->hw.next_desc = lower_32_bits(next); + segment->hw.next_desc_msb = upper_32_bits(next); } static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw) @@ -786,7 +796,7 @@ static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw) static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan, struct xilinx_axidma_tx_segment *segment) { - xilinx_dma_clean_hw_desc(&segment->hw); + xilinx_dma_clean_hw_desc(chan, segment); list_add_tail(&segment->node, &chan->free_seg_list); } @@ -920,9 +930,9 @@ static void xilinx_dma_free_descriptors(struct xilinx_dma_chan *chan) spin_lock_irqsave(&chan->lock, flags); - xilinx_dma_free_desc_list(chan, &chan->pending_list); xilinx_dma_free_desc_list(chan, &chan->done_list); xilinx_dma_free_desc_list(chan, &chan->active_list); + xilinx_dma_free_desc_list(chan, &chan->pending_list); spin_unlock_irqrestore(&chan->lock, flags); } |
