Re: [PATCH v2 63/64] dmaengine: qcom-gpi: defer callbacks via vchan
[email protected] Mon, 27 Jul 2026 21:24:57 +0000
| Newsgroups | org.kernel.vger.dmaengine |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Incorrect teardown sequence in gpi_free_chan_resources(): dma_chan_kill_bh() is called after gpi_free_ring(), exposing a freed ring buffer to concurrent client callbacks, leading to a divide-by-zero crash. - [High] The driver defers callbacks to a virt-dma BH but fails to implement the device_synchronize callback, breaking dmaengine_terminate_sync(). -- --- Patch [63]: [PATCH v2 63/64] dmaengine: qcom-gpi: defer callbacks via vchan --- commit e55f43a67f69dbf222b5c7eba067eedde92ac98b Author: Allen Pais <[email protected]> dmaengine: qcom-gpi: defer callbacks via vchan Complete descriptors through virt-dma instead of invoking callbacks directly from event processing. This preserves the transfer result for the shared vchan BH, which invokes the callback and frees the descriptor; drain that BH before releasing channel resources. > diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c > index a5055a6273af6..4cf68cf8eb2e5 100644 > --- a/drivers/dma/qcom/gpi.c > +++ b/drivers/dma/qcom/gpi.c [ ... ] > @@ -1060,8 +1064,12 @@ static void gpi_process_xfer_compl_event(struct gchan *gchan, > result.residue = gpi_desc->len - compl_event->length; > dev_dbg(gpii->gpi_dev->dev, "Residue %d\n", result.residue); > > - dma_cookie_complete(&vd->tx); > - dmaengine_desc_get_callback_invoke(&vd->tx, &result); > + spin_lock_irqsave(&gchan->vc.lock, flags); > + list_del(&vd->node); > + vd->tx_result = result; > + vchan_cookie_complete(vd); [Severity: High] Since this patch defers callbacks to the virt-dma bottom-half, does the driver now need to implement the device_synchronize callback? When a client driver calls dmaengine_terminate_sync() to ensure no callbacks are running before freeing its DMA buffers, the absence of device_synchronize causes it to fall back to dmaengine_terminate_all(), which merely stops the hardware. Could the newly introduced deferred BH execute a completion callback after dmaengine_terminate_sync() has already returned, potentially leading to a use-after-free in the client driver? Should gpi_probe() be updated to set gpi_dev->dma_device.device_synchronize to a function that wraps vchan_synchronize()? > + spin_unlock_irqrestore(&gchan->vc.lock, flags); > + return; > > gpi_free_desc: > spin_lock_irqsave(&gchan->vc.lock, flags); [ ... ] > @@ -2009,6 +2017,7 @@ static void gpi_free_chan_resources(struct dma_chan *chan) > > /* free all allocated memory */ > gpi_free_ring(&gchan->ch_ring, gpii); > + dma_chan_kill_bh(&gchan->vc.chan); [Severity: High] Does this cleanup sequence introduce a race condition that could result in a divide-by-zero crash? Because dma_chan_kill_bh() is called after gpi_free_ring(), the bottom-half is still permitted to run after the channel's ring has been freed and zero-initialized. If a deferred callback executes in the BH and calls dmaengine_prep_slave_sg() to queue the next transfer, it will eventually call gpi_prep_slave_sg(). That function calls gpi_ring_num_elements_avail(), which blindly accesses the now zeroed ch_ring and divides by ring->el_size. Could dma_chan_kill_bh() be moved before gpi_free_ring() to ensure the BH is drained before tearing down the hardware ring resources? > vchan_free_chan_resources(&gchan->vc); > kfree(gchan->config); > -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=63