Re: [PATCH v3 1/3] dmaengine: Fix device kref underflow in dma_chan_put()
Frank Li <[email protected]>
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <aoMYDJ3TdCIqTbEd@SMW015318> |
On Sun, Aug 16, 2026 at 03:49:25PM +0000, Shivank Garg wrote: > [You don't often get email from [email protected]. 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 <[email protected]> > --- Nit: add helper dma_device_get() to match dma_device_put() to make code more symmetry. Reviewed-by: Frank Li <[email protected]> > 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 >