[1/2] dmaengine: use dma_chan_name() helper to get per-channel device name

Message ID 20260812-dma-chan_dev-rename-v1-1-a67131f7d5c2@nxp.com (mailing list archive)
State New
Headers
Series dmaengine: rename dma_chan::dev to dma_chan::chan_dev for clarity |

Commit Message

Frank Li Aug. 12, 2026, 9:24 p.m. UTC
From: Frank Li <Frank.Li@nxp.com>

Use the existing dma_chan_name() helper to obtain the per-channel device
name instead of open-coding: dev_name(chan->dev->device) /
dev_name(chan2dev())

Simplify the code and improve consistency.

No functional change intended.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/arm-dma350.c                       | 2 +-
 drivers/dma/dma-jz4780.c                       | 2 +-
 drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 2 +-
 drivers/dma/idma64.c                           | 2 +-
 drivers/dma/loongson/loongson2-apb-cmc-dma.c   | 2 +-
 drivers/dma/loongson/loongson2-apb-dma.c       | 2 +-
 drivers/dma/mmp_pdma.c                         | 2 +-
 drivers/dma/st_fdma.c                          | 2 +-
 drivers/dma/stm32/stm32-dma.c                  | 2 +-
 drivers/dma/stm32/stm32-dma3.c                 | 6 +++---
 drivers/dma/stm32/stm32-mdma.c                 | 2 +-
 include/trace/events/tegra_apb_dma.h           | 6 +++---
 12 files changed, 16 insertions(+), 16 deletions(-)
  

Comments

sashiko-bot@kernel.org Aug. 12, 2026, 9:34 p.m. UTC | #1
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Probe error path prematurely frees DMA channel structures and disables clocks before devm-managed IRQs are freed, leading to a Use-After-Free and potential bus hang.
--

--- Patch [1]: [PATCH 1/2] dmaengine: use dma_chan_name() helper to get per-channel device name ---
commit 77ba32b52a0d71c14db9e5276f81ba0fa2896131
Author: Frank Li <Frank.Li@nxp.com>

dmaengine: use dma_chan_name() helper to get per-channel device name

This patch uses the existing dma_chan_name() helper to obtain the
per-channel device name instead of open-coding it. This simplifies the
code and improves consistency.

[ ... ]

> diff --git a/drivers/dma/stm32/stm32-dma.c b/drivers/dma/stm32/stm32-dma.c
> index d3ad78562a140..4e3ecb6763036 100644
> --- a/drivers/dma/stm32/stm32-dma.c
> +++ b/drivers/dma/stm32/stm32-dma.c
> @@ -1668,7 +1668,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
>  
>  		ret = devm_request_irq(&pdev->dev, chan->irq,
>  				       stm32_dma_chan_irq, 0,
> -				       dev_name(chan2dev(chan)), chan);
> +				       dma_chan_name(&chan->vchan.chan), chan);

[Severity: High]
This is a pre-existing issue and was not introduced by the patch under
review, but doesn't the error path in stm32_dma_probe() in
drivers/dma/stm32/stm32-dma.c prematurely free DMA channel structures and
disable clocks before the devm-managed IRQs are freed?

In stm32_dma_probe(), IRQs are requested using devm_request_irq() and
passed dma_chan_name(&chan->vchan.chan) as the action name.

If a subsequent initialization step fails, the error path manually calls
dma_async_device_unregister(dd):

err_unregister:
	dma_async_device_unregister(dd);
clk_free:
	clk_disable_unprepare(dmadev->clk);

	return ret;

This frees the channel device structures, including the embedded name
string, and clk_disable_unprepare(dmadev->clk) stops the hardware clock.

Because the IRQs are devres-managed, they remain active until the probe
function returns and the devres framework unwinds. During this window, if
/proc/interrupts is read, the kernel accesses the freed action->name
string, potentially triggering a Use-After-Free.

Furthermore, if a spurious interrupt fires during this window, the handler
stm32_dma_chan_irq() will read hardware registers with the device clock
disabled, which could trigger a Data Abort kernel panic.

>  		if (ret) {
>  			dev_err(&pdev->dev,
>  				"request_irq failed with err %d channel %d\n",
  
Logan Gunthorpe Aug. 13, 2026, 5:28 p.m. UTC | #2
On 2026-08-12 3:24 p.m., Frank.Li@oss.nxp.com wrote:
> From: Frank Li <Frank.Li@nxp.com>
> 
> Use the existing dma_chan_name() helper to obtain the per-channel device
> name instead of open-coding: dev_name(chan->dev->device) /
> dev_name(chan2dev())
> 
> Simplify the code and improve consistency.
> 
> No functional change intended.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>

Makes sense to me.

Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
  
Andy Shevchenko Aug. 14, 2026, 8:03 a.m. UTC | #3
On Wed, Aug 12, 2026 at 05:24:08PM -0400, Frank.Li@oss.nxp.com wrote:

> Use the existing dma_chan_name() helper to obtain the per-channel device
> name instead of open-coding: dev_name(chan->dev->device) /
> dev_name(chan2dev())
> 
> Simplify the code and improve consistency.
> 
> No functional change intended.

...

>  		ret = devm_request_irq(dev, lchan->irq, loongson2_cmc_dma_chan_irq, IRQF_SHARED,
> -				       dev_name(chan2dev(lchan)), lchan);
> +				       dma_chan_name(&lchan->vchan.chan), lchan);

Depending on the amount of users (and I expect there is a number), I would
expect specific API for virt-dma case.

>  		if (ret)
>  			return ret;
  
Frank Li Aug. 14, 2026, 4:15 p.m. UTC | #4
On Fri, Aug 14, 2026 at 11:03:48AM +0300, Andy Shevchenko wrote:
> On Wed, Aug 12, 2026 at 05:24:08PM -0400, Frank.Li@oss.nxp.com wrote:
>
> > Use the existing dma_chan_name() helper to obtain the per-channel device
> > name instead of open-coding: dev_name(chan->dev->device) /
> > dev_name(chan2dev())
> >
> > Simplify the code and improve consistency.
> >
> > No functional change intended.
>
> ...
>
> >  		ret = devm_request_irq(dev, lchan->irq, loongson2_cmc_dma_chan_irq, IRQF_SHARED,
> > -				       dev_name(chan2dev(lchan)), lchan);
> > +				       dma_chan_name(&lchan->vchan.chan), lchan);
>
> Depending on the amount of users (and I expect there is a number), I would
> expect specific API for virt-dma case.

Make sense, I consider it before. Let's wait for while for patch2's comments

Frank
>
> >  		if (ret)
> >  			return ret;
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
  

Patch

diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
index 09403aca8bb06..89673a5fca304 100644
--- a/drivers/dma/arm-dma350.c
+++ b/drivers/dma/arm-dma350.c
@@ -512,7 +512,7 @@  static int d350_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct d350_chan *dch = to_d350_chan(chan);
 	int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED,
-			      dev_name(&dch->vc.chan.dev->device), dch);
+			      dma_chan_name(&dch->vc.chan), dch);
 	if (!ret)
 		writel_relaxed(CH_INTREN_DONE | CH_INTREN_ERR, dch->base + CH_INTREN);
 
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index 6070dfdb7114c..194649811d02b 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -760,7 +760,7 @@  static int jz4780_dma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
 
-	jzchan->desc_pool = dma_pool_create(dev_name(&chan->dev->device),
+	jzchan->desc_pool = dma_pool_create(dma_chan_name(chan),
 					    chan->device->dev,
 					    JZ_DMA_DESC_BLOCK_SIZE,
 					    PAGE_SIZE, 0);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index eebed2474210d..d24902374f742 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -531,7 +531,7 @@  static int dma_chan_alloc_chan_resources(struct dma_chan *dchan)
 	}
 
 	/* LLI address must be aligned to a 64-byte boundary */
-	chan->desc_pool = dma_pool_create(dev_name(chan2dev(chan)),
+	chan->desc_pool = dma_pool_create(dma_chan_name(dchan),
 					  chan->chip->dev,
 					  sizeof(struct axi_dma_lli),
 					  64, 0);
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 5fcd1befc92da..6399fd5408be2 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -507,7 +507,7 @@  static int idma64_alloc_chan_resources(struct dma_chan *chan)
 	struct idma64_chan *idma64c = to_idma64_chan(chan);
 
 	/* Create a pool of consistent memory blocks for hardware descriptors */
-	idma64c->pool = dma_pool_create(dev_name(chan2dev(chan)),
+	idma64c->pool = dma_pool_create(dma_chan_name(chan),
 					chan->device->dev,
 					sizeof(struct idma64_lli), 8, 0);
 	if (!idma64c->pool) {
diff --git a/drivers/dma/loongson/loongson2-apb-cmc-dma.c b/drivers/dma/loongson/loongson2-apb-cmc-dma.c
index 1c9a542edc859..f53f24b7f8ffe 100644
--- a/drivers/dma/loongson/loongson2-apb-cmc-dma.c
+++ b/drivers/dma/loongson/loongson2-apb-cmc-dma.c
@@ -678,7 +678,7 @@  static int loongson2_cmc_dma_probe(struct platform_device *pdev)
 			return lchan->irq;
 
 		ret = devm_request_irq(dev, lchan->irq, loongson2_cmc_dma_chan_irq, IRQF_SHARED,
-				       dev_name(chan2dev(lchan)), lchan);
+				       dma_chan_name(&lchan->vchan.chan), lchan);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/dma/loongson/loongson2-apb-dma.c b/drivers/dma/loongson/loongson2-apb-dma.c
index aceb069e71fca..7c3d7c3273955 100644
--- a/drivers/dma/loongson/loongson2-apb-dma.c
+++ b/drivers/dma/loongson/loongson2-apb-dma.c
@@ -282,7 +282,7 @@  static int ls2x_dma_alloc_chan_resources(struct dma_chan *chan)
 	struct ls2x_dma_chan *lchan = to_ldma_chan(chan);
 
 	/* Create a pool of consistent memory blocks for hardware descriptors */
-	lchan->pool = dma_pool_create(dev_name(chan2dev(chan)),
+	lchan->pool = dma_pool_create(dma_chan_name(chan),
 				      chan->device->dev, PAGE_SIZE,
 				      __alignof__(struct ls2x_dma_hw_desc), 0);
 	if (!lchan->pool) {
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 386e85cd4882a..6b29e15b0616c 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -565,7 +565,7 @@  static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
 	if (chan->desc_pool)
 		return 1;
 
-	chan->desc_pool = dma_pool_create(dev_name(&dchan->dev->device),
+	chan->desc_pool = dma_pool_create(dma_chan_name(dchan),
 					  chan->dev,
 					  sizeof(struct mmp_pdma_desc_sw),
 					  __alignof__(struct mmp_pdma_desc_sw),
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index d9547017f3bd6..35dbff5f9f1ab 100644
--- a/drivers/dma/st_fdma.c
+++ b/drivers/dma/st_fdma.c
@@ -268,7 +268,7 @@  static int st_fdma_alloc_chan_res(struct dma_chan *chan)
 	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
 
 	/* Create the dma pool for descriptor allocation */
-	fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device),
+	fchan->node_pool = dma_pool_create(dma_chan_name(chan),
 					    fchan->fdev->dev,
 					    sizeof(struct st_fdma_hw_node),
 					    __alignof__(struct st_fdma_hw_node),
diff --git a/drivers/dma/stm32/stm32-dma.c b/drivers/dma/stm32/stm32-dma.c
index d3ad78562a140..4e3ecb6763036 100644
--- a/drivers/dma/stm32/stm32-dma.c
+++ b/drivers/dma/stm32/stm32-dma.c
@@ -1668,7 +1668,7 @@  static int stm32_dma_probe(struct platform_device *pdev)
 
 		ret = devm_request_irq(&pdev->dev, chan->irq,
 				       stm32_dma_chan_irq, 0,
-				       dev_name(chan2dev(chan)), chan);
+				       dma_chan_name(&chan->vchan.chan), chan);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"request_irq failed with err %d channel %d\n",
diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
index 4724e7fa0008e..ab0fb05597363 100644
--- a/drivers/dma/stm32/stm32-dma3.c
+++ b/drivers/dma/stm32/stm32-dma3.c
@@ -1126,7 +1126,7 @@  static int stm32_dma3_alloc_chan_resources(struct dma_chan *c)
 		goto err_put_sync;
 	}
 
-	chan->lli_pool = dmam_pool_create(dev_name(&c->dev->device), c->device->dev,
+	chan->lli_pool = dmam_pool_create(dma_chan_name(c), c->device->dev,
 					  sizeof(struct stm32_dma3_hwdesc),
 					  __alignof__(struct stm32_dma3_hwdesc), SZ_64K);
 	if (!chan->lli_pool) {
@@ -1892,10 +1892,10 @@  static int stm32_dma3_probe(struct platform_device *pdev)
 		chan->irq = ret;
 
 		ret = devm_request_irq(&pdev->dev, chan->irq, stm32_dma3_chan_irq, 0,
-				       dev_name(chan2dev(chan)), chan);
+				       dma_chan_name(&chan->vchan.chan), chan);
 		if (ret) {
 			dev_err_probe(&pdev->dev, ret, "Failed to request channel %s IRQ\n",
-				      dev_name(chan2dev(chan)));
+				      dma_chan_name(&chan->vchan.chan));
 			goto err_clk_disable;
 		}
 	}
diff --git a/drivers/dma/stm32/stm32-mdma.c b/drivers/dma/stm32/stm32-mdma.c
index e3bbdc9ee36ed..c274638e919c2 100644
--- a/drivers/dma/stm32/stm32-mdma.c
+++ b/drivers/dma/stm32/stm32-mdma.c
@@ -1484,7 +1484,7 @@  static int stm32_mdma_alloc_chan_resources(struct dma_chan *c)
 	struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan);
 	int ret;
 
-	chan->desc_pool = dmam_pool_create(dev_name(&c->dev->device),
+	chan->desc_pool = dmam_pool_create(dma_chan_name(c),
 					   c->device->dev,
 					   sizeof(struct stm32_mdma_hwdesc),
 					  __alignof__(struct stm32_mdma_hwdesc),
diff --git a/include/trace/events/tegra_apb_dma.h b/include/trace/events/tegra_apb_dma.h
index 6d9f5075baa3e..c38117c127ef3 100644
--- a/include/trace/events/tegra_apb_dma.h
+++ b/include/trace/events/tegra_apb_dma.h
@@ -11,7 +11,7 @@  TRACE_EVENT(tegra_dma_tx_status,
 	TP_PROTO(struct dma_chan *dc, dma_cookie_t cookie, struct dma_tx_state *state),
 	TP_ARGS(dc, cookie, state),
 	TP_STRUCT__entry(
-		__string(chan,	dev_name(&dc->dev->device))
+		__string(chan,	dma_chan_name(dc))
 		__field(dma_cookie_t, cookie)
 		__field(__u32,	residue)
 	),
@@ -28,7 +28,7 @@  TRACE_EVENT(tegra_dma_complete_cb,
 	TP_PROTO(struct dma_chan *dc, int count, void *ptr),
 	TP_ARGS(dc, count, ptr),
 	TP_STRUCT__entry(
-		__string(chan,	dev_name(&dc->dev->device))
+		__string(chan,	dma_chan_name(dc))
 		__field(int,	count)
 		__field(void *,	ptr)
 		),
@@ -45,7 +45,7 @@  TRACE_EVENT(tegra_dma_isr,
 	TP_PROTO(struct dma_chan *dc, int irq),
 	TP_ARGS(dc, irq),
 	TP_STRUCT__entry(
-		__string(chan,	dev_name(&dc->dev->device))
+		__string(chan,	dma_chan_name(dc))
 		__field(int,	irq)
 	),
 	TP_fast_assign(