Re: [PATCH 2/6] dmaengine: plx_dma: fix descriptor ring leak in alloc_chan_resources()

From: Frank Li

Date: Fri Nov 06 2026 - 12:28:58 EST


On Tue, Nov 03, 2026 at 09:51:57AM -0600, Logan Gunthorpe wrote:
> If the device is removed between plx_dma_alloc_desc() and the pdev
> check, the error path frees hw_ring but leaks desc_ring and every
> descriptor in it.
>
> Add plx_dma_free_desc() and use it here and in
> plx_dma_free_chan_resources().
>
> Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
> Link: https://lore.kernel.org/dmaengine/20260717223217.B6FBF1F000E9@xxxxxxxxxxxxxxx
> Signed-off-by: Logan Gunthorpe <logang@xxxxxxxxxxxx>
> ---
> drivers/dma/plx_dma.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)

Reviewed-by: Frank Li <Frank.Li@xxxxxxx>

>
> diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
> index 0a7ad2473cb1..bfccbb0c70e8 100644
> --- a/drivers/dma/plx_dma.c
> +++ b/drivers/dma/plx_dma.c
> @@ -404,6 +404,16 @@ static int plx_dma_alloc_desc(struct plx_dma_dev *plxdev)
> return -ENOMEM;
> }
>
> +static void plx_dma_free_desc(struct plx_dma_dev *plxdev)
> +{
> + int i;
> +
> + for (i = 0; i < PLX_DMA_RING_COUNT; i++)
> + kfree(plxdev->desc_ring[i]);
> +
> + kfree(plxdev->desc_ring);
> +}
> +
> static int plx_dma_alloc_chan_resources(struct dma_chan *chan)
> {
> struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
> @@ -424,7 +434,7 @@ static int plx_dma_alloc_chan_resources(struct dma_chan *chan)
> if (!rcu_dereference(plxdev->pdev)) {
> rcu_read_unlock();
> rc = -ENODEV;
> - goto out_free_hw_ring;
> + goto out_free_desc;
> }
>
> writel(PLX_REG_CTRL_RESET_VAL, plxdev->bar + PLX_REG_CTRL);
> @@ -443,6 +453,8 @@ static int plx_dma_alloc_chan_resources(struct dma_chan *chan)
>
> return PLX_DMA_RING_COUNT;
>
> +out_free_desc:
> + plx_dma_free_desc(plxdev);
> out_free_hw_ring:
> dma_free_coherent(plxdev->dma_dev.dev, ring_sz, plxdev->hw_ring,
> plxdev->hw_ring_dma);
> @@ -454,7 +466,6 @@ static void plx_dma_free_chan_resources(struct dma_chan *chan)
> struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
> size_t ring_sz = PLX_DMA_RING_COUNT * sizeof(*plxdev->hw_ring);
> int irq = -1;
> - int i;
>
> spin_lock_bh(&plxdev->ring_lock);
> plxdev->ring_active = false;
> @@ -474,10 +485,7 @@ static void plx_dma_free_chan_resources(struct dma_chan *chan)
>
> plx_dma_abort_desc(plxdev);
>
> - for (i = 0; i < PLX_DMA_RING_COUNT; i++)
> - kfree(plxdev->desc_ring[i]);
> -
> - kfree(plxdev->desc_ring);
> + plx_dma_free_desc(plxdev);
> dma_free_coherent(plxdev->dma_dev.dev, ring_sz, plxdev->hw_ring,
> plxdev->hw_ring_dma);
>
> --
> 2.47.3
>