Re: [PATCH v4 2/4] dmaengine: Fix device kref underflow in dma_chan_put()
From: Logan Gunthorpe
Date: Tue Aug 18 2026 - 11:52:18 EST
On 2026-08-17 21:43, Shivank Garg wrote:
> 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;
> if (!dma_device_get(chan->device)) { // calls kref_get_unless_zero()
>
> 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")
> Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
> Signed-off-by: Shivank Garg <shivankg@xxxxxxx>
Looks good to me, thanks.
Reviewed-by: Logan Gunthorpe <logang@xxxxxxxxxxxx>