Re: [PATCH v3 1/3] dmaengine: Fix device kref underflow in dma_chan_put()
From: Frank Li
Date: Mon Aug 17 2026 - 10:45:05 EST
On Sun, Aug 16, 2026 at 03:49:25PM +0000, Shivank Garg wrote:
> [You don't often get email from shivankg@xxxxxxx. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> dma_chan_get() takes chan->device->ref only on the slow path:
>
> /* no kref on fast path */
> if (chan->client_count) {
> __module_get(owner);
> chan->client_count++;
> return 0;
> }
> if (!try_module_get(owner))
> return -ENODEV;
> ret = kref_get_unless_zero(&chan->device->ref);
>
> dma_chan_put() drops the ref unconditionally, so every fast-path
> get/put pair drops one extra device reference.
>
> The bug fires when two conditions hold together: a non-private
> provider has a persistent client holding chan->client_count > 0
> and another client cycles dmaengine_get()/dmaengine_put().
> When the kref hits zero, the subsequent dma_find_channel() returns
> NULL even though the provider module is still loaded.
>
> Fix this by dropping device->ref only on the last put, matching the
> single slow-path get.
>
> Fixes: 8ad342a86359 ("dmaengine: Add reference counting to dma_device struct")
> Signed-off-by: Shivank Garg <shivankg@xxxxxxx>
> ---
Nit: add helper dma_device_get() to match dma_device_put() to make code
more symmetry.
Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
> drivers/dma/dmaengine.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> index 6ffd8bd82154..516d6d933208 100644
> --- a/drivers/dma/dmaengine.c
> +++ b/drivers/dma/dmaengine.c
> @@ -515,7 +515,9 @@ static void dma_chan_put(struct dma_chan *chan)
> chan->route_data = NULL;
> }
>
> - dma_device_put(chan->device);
> + /* This channel is not in use anymore, drop the device ref */
> + if (!chan->client_count)
> + dma_device_put(chan->device);
> module_put(dma_chan_to_owner(chan));
> }
>
>
> --
> 2.43.0
>