Skip to contentSkip to conversation

dmaengine: fix device leaks

PATCH Applied Johan Hovold 8 participants 35 messages Nov 17, 2025 – Dec 16, 2025

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

cover dmaengine: fix device leaks

The dmaengine drivers pretty consistently failed to release references taken when looking up devices using of_find_device_by_node() and similar helpers.

Included are also two OF node leak fixes and a couple of related cleanups.

Johan

Johan Hovold (15):
dmaengine: at_hdmac: fix device leak on of_dma_xlate()
dmaengine: bcm-sba-raid: fix device leak on probe
dmaengine: cv1800b-dmamux: fix device leak on route allocation
dmaengine: dw: dmamux: fix OF node leak on route allocation failure
dmaengine: idxd: fix device leaks on compat bind and unbind
dmaengine: lpc18xx-dmamux: fix device leak on route allocation
dmaengine: lpc32xx-dmamux: fix device leak on route allocation
dmaengine: sh: rz-dmac: fix device leak on probe failure
dmaengine: stm32: dmamux: fix device leak on route allocation
dmaengine: stm32: dmamux: fix OF node leak on route allocation failure
dmaengine: stm32: dmamux: clean up route allocation error labels
dmaengine: ti: dma-crossbar: fix device leak on dra7x route allocation
dmaengine: ti: dma-crossbar: fix device leak on am335x route
allocation
dmaengine: ti: dma-crossbar: clean up dra7x route allocation error
paths
dmaengine: ti: k3-udma: fix device leak on udma lookup

 drivers/dma/at_hdmac.c           |  9 ++++++--
 drivers/dma/bcm-sba-raid.c       |  6 +++++-
 drivers/dma/cv1800b-dmamux.c     | 17 +++++++++-------
 drivers/dma/dw/rzn1-dmamux.c     |  4 +++-
 drivers/dma/idxd/compat.c        | 23 +++++++++++++++++----
 drivers/dma/lpc18xx-dmamux.c     | 19 ++++++++++++-----
 drivers/dma/lpc32xx-dmamux.c     | 19 ++++++++++++-----
 drivers/dma/sh/rz-dmac.c         | 13 ++++++++++--
 drivers/dma/stm32/stm32-dmamux.c | 31 +++++++++++++++++-----------
 drivers/dma/ti/dma-crossbar.c    | 35 ++++++++++++++++++--------------
 drivers/dma/ti/k3-udma-private.c |  2 +-
 11 files changed, 123 insertions(+), 55 deletions(-)
Signature · 1 line
2.51.0
#1 lore raw

PATCH 1/15 dmaengine: at_hdmac: fix device leak on of_dma_xlate()

Make sure to drop the reference taken when looking up the DMA platform device during of_dma_xlate() when releasing channel resources.

Note that commit 3832b78b3ec2 ("dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()") fixed the leak in a couple of error paths but the reference is still leaking on successful allocation.

Fixes bbe89c8e3d59 ("at_hdmac: move to generic DMA binding")
Fixes 3832b78b3ec2 ("dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()")
Cc [email protected] # 3.10: 3832b78b3ec2
Cc Yu Kuai <[email protected]>
---
 drivers/dma/at_hdmac.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/dma/at_hdmac.c +7 -2
index 2d147712cbc6..dffe5becd6c3 100644
@@ -1765,6 +1765,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
 static void atc_free_chan_resources(struct dma_chan *chan)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_dma_slave	*atslave;
 
 	BUG_ON(atc_chan_is_enabled(atchan));
 
@@ -1774,8 +1775,12 @@ static void atc_free_chan_resources(struct dma_chan *chan)
 	/*
 	 * Free atslave allocated in at_dma_xlate()
 	 */
-	kfree(chan->private);
-	chan->private = NULL;
+	atslave = chan->private;
+	if (atslave) {
+		put_device(atslave->dma_dev);
+		kfree(atslave);
+		chan->private = NULL;
+	}
 
 	dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
 }
Signature · 1 line
2.51.0
#2 lore raw

Re: [PATCH 01/15] dmaengine: at_hdmac: fix device leak on of_dma_xlate()

Quoted 6 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA platform device during of_dma_xlate() when releasing channel resources.

Note that commit 3832b78b3ec2 ("dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()") fixed the leak in a couple of error paths but the reference is still leaking on successful allocation.

...

drivers/dma/at_hdmac.c static void atc_free_chan_resources(struct dma_chan *chan) · line 1783

Quoted 8 lines
drivers/dma/at_hdmac.c +6 -2
-	kfree(chan->private);
-	chan->private = NULL;
+	atslave = chan->private;
+	if (atslave) {
+		put_device(atslave->dma_dev);
+		kfree(atslave);
+		chan->private = NULL;
+	}

It can also be

	atslave = chan->private;
	if (atslave)
		put_device(atslave->dma_dev);
	kfree(chan->private);
	chan->private = NULL;

which makes patch shorter.

In any case I'm wondering if the asynchronous nature of put_device() can collide with chan->private = NULL assignment. I think as long as it's not used inside ->release() of the device, we are fine.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#3 lore raw

Re: [PATCH 01/15] dmaengine: at_hdmac: fix device leak on of_dma_xlate()

Quoted 21 lines · Andy Shevchenko
Quoted 6 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA platform device during of_dma_xlate() when releasing channel resources.

Note that commit 3832b78b3ec2 ("dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()") fixed the leak in a couple of error paths but the reference is still leaking on successful allocation.

...

drivers/dma/at_hdmac.c static void atc_free_chan_resources(struct dma_chan *chan) · line 1783

Quoted 8 lines
drivers/dma/at_hdmac.c +6 -2
-	kfree(chan->private);
-	chan->private = NULL;
+	atslave = chan->private;
+	if (atslave) {
+		put_device(atslave->dma_dev);
+		kfree(atslave);
+		chan->private = NULL;
+	}

It can also be

Quoted 7 lines
	atslave = chan->private;
	if (atslave)
		put_device(atslave->dma_dev);
	kfree(chan->private);
	chan->private = NULL;

which makes patch shorter.

Perhaps, but it would be less readable.

Quoted 3 lines

In any case I'm wondering if the asynchronous nature of put_device() can collide with chan->private = NULL assignment. I think as long as it's not used inside ->release() of the device, we are fine.

It's just another reference to the dma device which is not going away while it's channels are being tore down (or we would have bigger problems).

Johan

#4 lore raw

PATCH 1/1 dmaengine: ti: k3-udma: enable compile testing

In reply to Johan Hovold

There does not seem to be anything preventing the K3 UDMA drivers from being compile tested (on arm64 as one dependency depends on ARM64) so enable compile testing for wider build coverage.

Note that the ring accelerator dependency can only be selected when "TI SOC drivers support" (SOC_TI) is enabled so select that option too.

---
 drivers/dma/ti/Kconfig | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/dma/ti/Kconfig +3 -2
index dbf168146d35..cbc30ab62783 100644
@@ -36,11 +36,12 @@ config DMA_OMAP
 
 config TI_K3_UDMA
 	tristate "Texas Instruments UDMA support"
-	depends on ARCH_K3
+	depends on ARCH_K3 || COMPILE_TEST
 	depends on TI_SCI_PROTOCOL
 	depends on TI_SCI_INTA_IRQCHIP
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
+	select SOC_TI
 	select TI_K3_RINGACC
 	select TI_K3_PSIL
         help
@@ -49,7 +50,7 @@ config TI_K3_UDMA
 
 config TI_K3_UDMA_GLUE_LAYER
 	tristate "Texas Instruments UDMA Glue layer for non DMAengine users"
-	depends on ARCH_K3
+	depends on ARCH_K3 || COMPILE_TEST
 	depends on TI_K3_UDMA
 	help
 	  Say y here to support the K3 NAVSS DMA glue interface
Signature · 1 line
2.51.0
#5 lore raw

Re: [PATCH] dmaengine: ti: k3-udma: enable compile testing

Quoted 9 lines · Johan Hovold

There does not seem to be anything preventing the K3 UDMA drivers from being compile tested (on arm64 as one dependency depends on ARM64) so enable compile testing for wider build coverage.

Note that the ring accelerator dependency can only be selected when "TI SOC drivers support" (SOC_TI) is enabled so select that option too.

---

Please disregard this one which was supposed to be sent separately.

Johan

#6 lore raw

PATCH 2/15 dmaengine: bcm-sba-raid: fix device leak on probe

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the mailbox device during probe on probe failures and on driver unbind.

Fixes 743e1c8ffe4e ("dmaengine: Add Broadcom SBA RAID driver")
---
 drivers/dma/bcm-sba-raid.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/dma/bcm-sba-raid.c +5 -1
index 7f0e76439ce5..ed037fa883f6 100644
@@ -1699,7 +1699,7 @@ static int sba_probe(struct platform_device *pdev)
 	/* Prealloc channel resource */
 	ret = sba_prealloc_channel_resources(sba);
 	if (ret)
-		goto fail_free_mchan;
+		goto fail_put_mbox;
 
 	/* Check availability of debugfs */
 	if (!debugfs_initialized())
@@ -1729,6 +1729,8 @@ static int sba_probe(struct platform_device *pdev)
 fail_free_resources:
 	debugfs_remove_recursive(sba->root);
 	sba_freeup_channel_resources(sba);
+fail_put_mbox:
+	put_device(sba->mbox_dev);
 fail_free_mchan:
 	mbox_free_channel(sba->mchan);
 	return ret;
@@ -1744,6 +1746,8 @@ static void sba_remove(struct platform_device *pdev)
 
 	sba_freeup_channel_resources(sba);
 
+	put_device(sba->mbox_dev);
+
 	mbox_free_channel(sba->mchan);
 }
 
Signature · 1 line
2.51.0
#7 lore raw

PATCH 3/15 dmaengine: cv1800b-dmamux: fix device leak on route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes db7d07b5add4 ("dmaengine: add driver for Sophgo CV18XX/SG200X dmamux")
Cc Inochi Amaoto <[email protected]>
---
 drivers/dma/cv1800b-dmamux.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
drivers/dma/cv1800b-dmamux.c +10 -7
index e900d6595617..f7a952fcbc7d 100644
@@ -102,11 +102,11 @@ static void *cv1800_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	struct llist_node *node;
 	unsigned long flags;
 	unsigned int chid, devid, cpuid;
-	int ret;
+	int ret = -EINVAL;
 
 	if (dma_spec->args_count != DMAMUX_NCELLS) {
 		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	devid = dma_spec->args[0];
@@ -115,18 +115,18 @@ static void *cv1800_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 	if (devid > MAX_DMA_MAPPING_ID) {
 		dev_err(&pdev->dev, "invalid device id: %u\n", devid);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	if (cpuid > MAX_DMA_CPU_ID) {
 		dev_err(&pdev->dev, "invalid cpu id: %u\n", cpuid);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "can't get dma master\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	spin_lock_irqsave(&dmamux->lock, flags);
@@ -136,8 +136,6 @@ static void *cv1800_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 			if (map->peripheral == devid && map->cpu == cpuid)
 				goto found;
 		}
-
-		ret = -EINVAL;
 		goto failed;
 	} else {
 		node = llist_del_first(&dmamux->free_maps);
@@ -171,12 +169,17 @@ static void *cv1800_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	dev_dbg(&pdev->dev, "register channel %u for req %u (cpu %u)\n",
 		chid, devid, cpuid);
 
+	put_device(&pdev->dev);
+
 	return map;
 
 failed:
 	spin_unlock_irqrestore(&dmamux->lock, flags);
 	of_node_put(dma_spec->np);
 	dev_err(&pdev->dev, "errno %d\n", ret);
+err_put_pdev:
+	put_device(&pdev->dev);
+
 	return ERR_PTR(ret);
 }
 
Signature · 1 line
2.51.0
#8 lore raw

PATCH 4/15 dmaengine: dw: dmamux: fix OF node leak on route allocation failure

In reply to Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

Fixes 134d9c52fca2 ("dmaengine: dw: dmamux: Introduce RZN1 DMA router support")
Cc Miquel Raynal <[email protected]>
---
 drivers/dma/dw/rzn1-dmamux.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/dw/rzn1-dmamux.c +3 -1
index deadf135681b..cbec277af4dd 100644
@@ -90,7 +90,7 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 	if (test_and_set_bit(map->req_idx, dmamux->used_chans)) {
 		ret = -EBUSY;
-		goto free_map;
+		goto put_dma_spec_np;
 	}
 
 	mask = BIT(map->req_idx);
@@ -103,6 +103,8 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 clear_bitmap:
 	clear_bit(map->req_idx, dmamux->used_chans);
+put_dma_spec_np:
+	of_node_put(dma_spec->np);
 free_map:
 	kfree(map);
 put_device:
Signature · 1 line
2.51.0
#9 lore raw

Re: [PATCH 04/15] dmaengine: dw: dmamux: fix OF node leak on route allocation failure

Quoted 2 lines · Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

...

drivers/dma/dw/rzn1-dmamux.c static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, · line 107

Quoted 2 lines
drivers/dma/dw/rzn1-dmamux.c +2 -0
+put_dma_spec_np:
+	of_node_put(dma_spec->np);

Can we use __free() instead?

(Just in case you are going to question the appearance of cleanup.h and the
respective class in of.h, it's available in the closest stable, i.e. v6.1.108 onwards).

Signature · 2 lines
With Best Regards,
Andy Shevchenko
Reviewed-by
#10 lore raw

Re: [PATCH 04/15] dmaengine: dw: dmamux: fix OF node leak on route allocation failure

Hi Andy,

Quoted 10 lines · Andy Shevchenko
Quoted 2 lines · Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

...

drivers/dma/dw/rzn1-dmamux.c static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, · line 107

Quoted 2 lines
drivers/dma/dw/rzn1-dmamux.c +2 -0
+put_dma_spec_np:
+	of_node_put(dma_spec->np);

Can we use __free() instead?

I probably haven't followed closely enough, but I don't understand how __free() is best than of_node_put() in front of of_parse_phandle()? Especially since the doc clearly states

"Return: The device_node pointer with refcount incremented. Use of_node_put() on it when done."

Quoted 3 lines

(Just in case you are going to question the appearance of cleanup.h and the
respective class in of.h, it's available in the closest stable, i.e. v6.1.108 onwards).

I don't believe including a recent header is a good practice for stable inclusion anyway. I would recommend to let the commit as it is and in a follow-up patch, maybe, we can move to a newer API if we want. This way history between stable and mailine versions is easier to compare.

Thanks,
Miquèl

#11 lore raw

Re: [PATCH 04/15] dmaengine: dw: dmamux: fix OF node leak on route allocation failure

In reply to Andy Shevchenko
Quoted 10 lines · Andy Shevchenko
Quoted 2 lines · Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

...

drivers/dma/dw/rzn1-dmamux.c static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, · line 107

Quoted 2 lines
drivers/dma/dw/rzn1-dmamux.c +2 -0
+put_dma_spec_np:
+	of_node_put(dma_spec->np);

Can we use __free() instead?

I'm no fan of __free() but here it's a particularly bad fit, so no.

Johan

#12 lore raw

PATCH 5/15 dmaengine: idxd: fix device leaks on compat bind and unbind

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the idxd device as part of the compat bind and unbind sysfs interface.

Fixes 6e7f3ee97bbe ("dmaengine: idxd: move dsa_drv support to compatible mode")
Cc Dave Jiang <[email protected]>
---
 drivers/dma/idxd/compat.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)
drivers/dma/idxd/compat.c +19 -4
index eff9943f1a42..95b8ef958633 100644
@@ -20,11 +20,16 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t c
 	int rc = -ENODEV;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
-	if (dev && dev->driver) {
+	if (!dev)
+		return -ENODEV;
+
+	if (dev->driver) {
 		device_driver_detach(dev);
 		rc = count;
 	}
 
+	put_device(dev);
+
 	return rc;
 }
 static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, 0200, NULL, unbind_store);
@@ -38,9 +43,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t cou
 	struct idxd_dev *idxd_dev;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
-	if (!dev || dev->driver || drv != &dsa_drv.drv)
+	if (!dev)
 		return -ENODEV;
 
+	if (dev->driver || drv != &dsa_drv.drv)
+		goto err_put_dev;
+
 	idxd_dev = confdev_to_idxd_dev(dev);
 	if (is_idxd_dev(idxd_dev)) {
 		alt_drv = driver_find("idxd", bus);
@@ -53,13 +61,20 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t cou
 			alt_drv = driver_find("user", bus);
 	}
 	if (!alt_drv)
-		return -ENODEV;
+		goto err_put_dev;
 
 	rc = device_driver_attach(alt_drv, dev);
 	if (rc < 0)
-		return rc;
+		goto err_put_dev;
+
+	put_device(dev);
 
 	return count;
+
+err_put_dev:
+	put_device(dev);
+
+	return rc;
 }
 static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store);
 
Signature · 1 line
2.51.0
reviewer Reviewed-by on v1 5/15
#13 lore raw

Re: [PATCH 05/15] dmaengine: idxd: fix device leaks on compat bind and unbind

Quoted 7 lines · Johan Hovold

Make sure to drop the reference taken when looking up the idxd device as part of the compat bind and unbind sysfs interface.

Fixes 6e7f3ee97bbe ("dmaengine: idxd: move dsa_drv support to compatible mode")
Cc Dave Jiang <[email protected]>
Quoted 62 lines
 drivers/dma/idxd/compat.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)
drivers/dma/idxd/compat.c +19 -4
index eff9943f1a42..95b8ef958633 100644
@@ -20,11 +20,16 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t c
 	int rc = -ENODEV;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
-	if (dev && dev->driver) {
+	if (!dev)
+		return -ENODEV;
+
+	if (dev->driver) {
 		device_driver_detach(dev);
 		rc = count;
 	}
 
+	put_device(dev);
+
 	return rc;
 }
 static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, 0200, NULL, unbind_store);
@@ -38,9 +43,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t cou
 	struct idxd_dev *idxd_dev;
 
 	dev = bus_find_device_by_name(bus, NULL, buf);
-	if (!dev || dev->driver || drv != &dsa_drv.drv)
+	if (!dev)
 		return -ENODEV;
 
+	if (dev->driver || drv != &dsa_drv.drv)
+		goto err_put_dev;
+
 	idxd_dev = confdev_to_idxd_dev(dev);
 	if (is_idxd_dev(idxd_dev)) {
 		alt_drv = driver_find("idxd", bus);
@@ -53,13 +61,20 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t cou
 			alt_drv = driver_find("user", bus);
 	}
 	if (!alt_drv)
-		return -ENODEV;
+		goto err_put_dev;
 
 	rc = device_driver_attach(alt_drv, dev);
 	if (rc < 0)
-		return rc;
+		goto err_put_dev;
+
+	put_device(dev);
 
 	return count;
+
+err_put_dev:
+	put_device(dev);
+
+	return rc;
 }
 static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store);
 
#14 lore raw

Re: [PATCH 05/15] dmaengine: idxd: fix device leaks on compat bind and unbind

Quoted 6 lines · Dave Jiang
Quoted 3 lines · Johan Hovold

Make sure to drop the reference taken when looking up the idxd device as part of the compat bind and unbind sysfs interface.

Quoted 6 lines
Quoted 4 lines
Fixes 6e7f3ee97bbe ("dmaengine: idxd: move dsa_drv support to compatible mode")
Cc Dave Jiang <[email protected]>

Thanks for reviewing.

Note that something happened here with the end of your tag. Hopefully Vinod can fix that up when applying.

Johan

#15 lore raw

PATCH 6/15 dmaengine: lpc18xx-dmamux: fix device leak on route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes e5f4ae84be74 ("dmaengine: add driver for lpc18xx dmamux")
---
 drivers/dma/lpc18xx-dmamux.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/dma/lpc18xx-dmamux.c +14 -5
index 2b6436f4b193..d3ff521951b8 100644
@@ -57,30 +57,31 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 	struct lpc18xx_dmamux_data *dmamux = platform_get_drvdata(pdev);
 	unsigned long flags;
 	unsigned mux;
+	int ret = -EINVAL;
 
 	if (dma_spec->args_count != 3) {
 		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	mux = dma_spec->args[0];
 	if (mux >= dmamux->dma_master_requests) {
 		dev_err(&pdev->dev, "invalid mux number: %d\n",
 			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	if (dma_spec->args[1] > LPC18XX_DMAMUX_MAX_VAL) {
 		dev_err(&pdev->dev, "invalid dma mux value: %d\n",
 			dma_spec->args[1]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	/* The of_node_put() will be done in the core for the node */
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "can't get dma master\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	spin_lock_irqsave(&dmamux->lock, flags);
@@ -89,7 +90,8 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 		dev_err(&pdev->dev, "dma request %u busy with %u.%u\n",
 			mux, mux, dmamux->muxes[mux].value);
 		of_node_put(dma_spec->np);
-		return ERR_PTR(-EBUSY);
+		ret = -EBUSY;
+		goto err_put_pdev;
 	}
 
 	dmamux->muxes[mux].busy = true;
@@ -106,7 +108,14 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 	dev_dbg(&pdev->dev, "mapping dmamux %u.%u to dma request %u\n", mux,
 		dmamux->muxes[mux].value, mux);
 
+	put_device(&pdev->dev);
+
 	return &dmamux->muxes[mux];
+
+err_put_pdev:
+	put_device(&pdev->dev);
+
+	return ERR_PTR(ret);
 }
 
 static int lpc18xx_dmamux_probe(struct platform_device *pdev)
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 6/15
#16 lore raw

Re: [PATCH 06/15] dmaengine: lpc18xx-dmamux: fix device leak on route allocation

Hi Johan.

Quoted 68 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes e5f4ae84be74 ("dmaengine: add driver for lpc18xx dmamux")
---
  drivers/dma/lpc18xx-dmamux.c | 19 ++++++++++++++-----
  1 file changed, 14 insertions(+), 5 deletions(-)
drivers/dma/lpc18xx-dmamux.c +8 -5
index 2b6436f4b193..d3ff521951b8 100644
@@ -57,30 +57,31 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  	struct lpc18xx_dmamux_data *dmamux = platform_get_drvdata(pdev);
  	unsigned long flags;
  	unsigned mux;
+	int ret = -EINVAL;
 
  	if (dma_spec->args_count != 3) {
  		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	mux = dma_spec->args[0];
  	if (mux >= dmamux->dma_master_requests) {
  		dev_err(&pdev->dev, "invalid mux number: %d\n",
  			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	if (dma_spec->args[1] > LPC18XX_DMAMUX_MAX_VAL) {
  		dev_err(&pdev->dev, "invalid dma mux value: %d\n",
  			dma_spec->args[1]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	/* The of_node_put() will be done in the core for the node */
  	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
  	if (!dma_spec->np) {
  		dev_err(&pdev->dev, "can't get dma master\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	spin_lock_irqsave(&dmamux->lock, flags);
@@ -89,7 +90,8 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  		dev_err(&pdev->dev, "dma request %u busy with %u.%u\n",
  			mux, mux, dmamux->muxes[mux].value);
  		of_node_put(dma_spec->np);
-		return ERR_PTR(-EBUSY);
+		ret = -EBUSY;
+		goto err_put_pdev;
  	}
 
  	dmamux->muxes[mux].busy = true;
@@ -106,7 +108,14 @@ static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  	dev_dbg(&pdev->dev, "mapping dmamux %u.%u to dma request %u\n", mux,
  		dmamux->muxes[mux].value, mux);
 
+	put_device(&pdev->dev);

drivers/dma/lpc18xx-dmamux.c static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec, · line 121

Quoted 10 lines
drivers/dma/lpc18xx-dmamux.c +6 -0
+
  	return &dmamux->muxes[mux];
+
+err_put_pdev:
+	put_device(&pdev->dev);
+
+	return ERR_PTR(ret);
  }
 
  static int lpc18xx_dmamux_probe(struct platform_device *pdev)
Signature · 2 lines
Best wishes,
Vladimir
#17 lore raw

Re: [PATCH 06/15] dmaengine: lpc18xx-dmamux: fix device leak on route allocation

Hi Vladimir,

Quoted 4 lines · Vladimir Zapolskiy
Quoted 3 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Quoted 8 lines
Quoted 6 lines

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes e5f4ae84be74 ("dmaengine: add driver for lpc18xx dmamux")

Thanks for reviewing.

Johan

#18 lore raw

PATCH 7/15 dmaengine: lpc32xx-dmamux: fix device leak on route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes 5d318b595982 ("dmaengine: Add dma router for pl08x in LPC32XX SoC")
Cc Piotr Wojtaszczyk <[email protected]>
---
 drivers/dma/lpc32xx-dmamux.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/dma/lpc32xx-dmamux.c +14 -5
index 351d7e23e615..33be714740dd 100644
@@ -95,11 +95,12 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 	struct lpc32xx_dmamux_data *dmamux = platform_get_drvdata(pdev);
 	unsigned long flags;
 	struct lpc32xx_dmamux *mux = NULL;
+	int ret = -EINVAL;
 	int i;
 
 	if (dma_spec->args_count != 3) {
 		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(lpc32xx_muxes); i++) {
@@ -111,20 +112,20 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 	if (!mux) {
 		dev_err(&pdev->dev, "invalid mux request number: %d\n",
 			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	if (dma_spec->args[2] > 1) {
 		dev_err(&pdev->dev, "invalid dma mux value: %d\n",
 			dma_spec->args[1]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	/* The of_node_put() will be done in the core for the node */
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "can't get dma master\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	spin_lock_irqsave(&dmamux->lock, flags);
@@ -133,7 +134,8 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 		dev_err(dev, "dma request signal %d busy, routed to %s\n",
 			mux->signal, mux->muxval ? mux->name_sel1 : mux->name_sel1);
 		of_node_put(dma_spec->np);
-		return ERR_PTR(-EBUSY);
+		ret = -EBUSY;
+		goto err_put_pdev;
 	}
 
 	mux->busy = true;
@@ -148,7 +150,14 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
 	dev_dbg(dev, "dma request signal %d routed to %s\n",
 		mux->signal, mux->muxval ? mux->name_sel1 : mux->name_sel1);
 
+	put_device(&pdev->dev);
+
 	return mux;
+
+err_put_pdev:
+	put_device(&pdev->dev);
+
+	return ERR_PTR(ret);
 }
 
 static int lpc32xx_dmamux_probe(struct platform_device *pdev)
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 7/15
#19 lore raw

Re: [PATCH 07/15] dmaengine: lpc32xx-dmamux: fix device leak on route allocation

Quoted 71 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes 5d318b595982 ("dmaengine: Add dma router for pl08x in LPC32XX SoC")
Cc Piotr Wojtaszczyk <[email protected]>
---
  drivers/dma/lpc32xx-dmamux.c | 19 ++++++++++++++-----
  1 file changed, 14 insertions(+), 5 deletions(-)
drivers/dma/lpc32xx-dmamux.c +8 -5
index 351d7e23e615..33be714740dd 100644
@@ -95,11 +95,12 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  	struct lpc32xx_dmamux_data *dmamux = platform_get_drvdata(pdev);
  	unsigned long flags;
  	struct lpc32xx_dmamux *mux = NULL;
+	int ret = -EINVAL;
  	int i;
 
  	if (dma_spec->args_count != 3) {
  		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	for (i = 0; i < ARRAY_SIZE(lpc32xx_muxes); i++) {
@@ -111,20 +112,20 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  	if (!mux) {
  		dev_err(&pdev->dev, "invalid mux request number: %d\n",
  			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	if (dma_spec->args[2] > 1) {
  		dev_err(&pdev->dev, "invalid dma mux value: %d\n",
  			dma_spec->args[1]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	/* The of_node_put() will be done in the core for the node */
  	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
  	if (!dma_spec->np) {
  		dev_err(&pdev->dev, "can't get dma master\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	spin_lock_irqsave(&dmamux->lock, flags);
@@ -133,7 +134,8 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  		dev_err(dev, "dma request signal %d busy, routed to %s\n",
  			mux->signal, mux->muxval ? mux->name_sel1 : mux->name_sel1);
  		of_node_put(dma_spec->np);
-		return ERR_PTR(-EBUSY);
+		ret = -EBUSY;
+		goto err_put_pdev;
  	}
 
  	mux->busy = true;
@@ -148,7 +150,14 @@ static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec,
  	dev_dbg(dev, "dma request signal %d routed to %s\n",
  		mux->signal, mux->muxval ? mux->name_sel1 : mux->name_sel1);
 
+	put_device(&pdev->dev);

drivers/dma/lpc32xx-dmamux.c static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec, · line 163

Quoted 10 lines
drivers/dma/lpc32xx-dmamux.c +6 -0
+
  	return mux;
+
+err_put_pdev:
+	put_device(&pdev->dev);
+
+	return ERR_PTR(ret);
  }
 
  static int lpc32xx_dmamux_probe(struct platform_device *pdev)
Signature · 2 lines
Best wishes,
Vladimir
#20 lore raw

PATCH 8/15 dmaengine: sh: rz-dmac: fix device leak on probe failure

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the ICU device during probe also on probe failures (e.g. probe deferral).

Fixes 7de873201c44 ("dmaengine: sh: rz-dmac: Add RZ/V2H(P) support")
Cc Fabrizio Castro <[email protected]>
---
 drivers/dma/sh/rz-dmac.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/dma/sh/rz-dmac.c +11 -2
index 1f687b08d6b8..38137e8d80b9 100644
@@ -854,6 +854,13 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
 	return 0;
 }
 
+static void rz_dmac_put_device(void *_dev)
+{
+	struct device *dev = _dev;
+
+	put_device(dev);
+}
+
 static int rz_dmac_parse_of_icu(struct device *dev, struct rz_dmac *dmac)
 {
 	struct device_node *np = dev->of_node;
@@ -876,6 +883,10 @@ static int rz_dmac_parse_of_icu(struct device *dev, struct rz_dmac *dmac)
 		return -ENODEV;
 	}
 
+	ret = devm_add_action_or_reset(dev, rz_dmac_put_device, &dmac->icu.pdev->dev);
+	if (ret)
+		return ret;
+
 	dmac_index = args.args[0];
 	if (dmac_index > RZV2H_MAX_DMAC_INDEX) {
 		dev_err(dev, "DMAC index %u invalid.\n", dmac_index);
@@ -1055,8 +1066,6 @@ static void rz_dmac_remove(struct platform_device *pdev)
 	reset_control_assert(dmac->rstc);
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-
-	platform_device_put(dmac->icu.pdev);
 }
 
 static const struct of_device_id of_rz_dmac_match[] = {
Signature · 1 line
2.51.0
Reviewed-by on v1 8/15
#21 lore raw

RE: [PATCH 08/15] dmaengine: sh: rz-dmac: fix device leak on probe failure

Quoted 12 lines

From: Johan Hovold <[email protected]>
Sent: 17 November 2025 16:13
To: Vinod Koul <[email protected]>
Cc: Ludovic Desroches <[email protected]>; Viresh Kumar <[email protected]>; Andy Shevchenko <[email protected]>; Vinicius Costa Gomes <[email protected]>; Dave Jiang <[email protected]>; Vladimir Zapolskiy <[email protected]>; Piotr Wojtaszczyk <[email protected]>; Amélie Delaunay <[email protected]>; Maxime Coquelin <[email protected]>; Alexandre Torgue <[email protected]>; Peter Ujfalusi <[email protected]>; [email protected]; [email protected]; Johan Hovold <[email protected]>; [email protected]; Fabrizio Castro <[email protected]>
Subject: [PATCH 08/15] dmaengine: sh: rz-dmac: fix device leak on probe failure

Quoted 7 lines

Make sure to drop the reference taken when looking up the ICU device during probe also on probe failures (e.g. probe deferral).

Fixes 7de873201c44 ("dmaengine: sh: rz-dmac: Add RZ/V2H(P) support")
Cc Fabrizio Castro <[email protected]>
Quoted 44 lines
---
 drivers/dma/sh/rz-dmac.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/dma/sh/rz-dmac.c +11 -3
index 1f687b08d6b8..38137e8d80b9 100644
@@ -854,6 +854,13 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
 	return 0;
 }
 
+static void rz_dmac_put_device(void *_dev)
+{
+	struct device *dev = _dev;
+
+	put_device(dev);
+}
+
 static int rz_dmac_parse_of_icu(struct device *dev, struct rz_dmac *dmac)
 {
 	struct device_node *np = dev->of_node;
@@ -876,6 +883,10 @@ static int rz_dmac_parse_of_icu(struct device *dev, struct rz_dmac *dmac)
 		return -ENODEV;
 	}
 
+	ret = devm_add_action_or_reset(dev, rz_dmac_put_device, &dmac->icu.pdev->dev);
+	if (ret)
+		return ret;
+
 	dmac_index = args.args[0];
 	if (dmac_index > RZV2H_MAX_DMAC_INDEX) {
 		dev_err(dev, "DMAC index %u invalid.\n", dmac_index);
@@ -1055,8 +1066,6 @@ static void rz_dmac_remove(struct platform_device *pdev)
 	reset_control_assert(dmac->rstc);
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-
-	platform_device_put(dmac->icu.pdev);
 }
 
 static const struct of_device_id of_rz_dmac_match[] = {
--

2.51.0

#22 lore raw

PATCH 9/15 dmaengine: stm32: dmamux: fix device leak on route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
Cc Pierre-Yves MORDRET <[email protected]>
---
 drivers/dma/stm32/stm32-dmamux.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/dma/stm32/stm32-dmamux.c +12 -6
index 8d77e2a7939a..791179760782 100644
@@ -90,23 +90,25 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	struct stm32_dmamux_data *dmamux = platform_get_drvdata(pdev);
 	struct stm32_dmamux *mux;
 	u32 i, min, max;
-	int ret;
+	int ret = -EINVAL;
 	unsigned long flags;
 
 	if (dma_spec->args_count != 3) {
 		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	if (dma_spec->args[0] > dmamux->dmamux_requests) {
 		dev_err(&pdev->dev, "invalid mux request number: %d\n",
 			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
 	}
 
 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
-	if (!mux)
-		return ERR_PTR(-ENOMEM);
+	if (!mux) {
+		ret = -ENOMEM;
+		goto err_put_pdev;
+	}
 
 	spin_lock_irqsave(&dmamux->lock, flags);
 	mux->chan_id = find_first_zero_bit(dmamux->dma_inuse,
@@ -133,7 +135,6 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "can't get dma master\n");
-		ret = -EINVAL;
 		goto error;
 	}
 
@@ -160,6 +161,8 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	dev_dbg(&pdev->dev, "Mapping DMAMUX(%u) to DMA%u(%u)\n",
 		mux->request, mux->master, mux->chan_id);
 
+	put_device(&pdev->dev);
+
 	return mux;
 
 error:
@@ -167,6 +170,9 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 error_chan_id:
 	kfree(mux);
+err_put_pdev:
+	put_device(&pdev->dev);
+
 	return ERR_PTR(ret);
 }
 
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 9/15
#23 lore raw

Re: [PATCH 09/15] dmaengine: stm32: dmamux: fix device leak on route allocation

Quoted 10 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
Cc Pierre-Yves MORDRET <[email protected]>
Quoted 66 lines
---
  drivers/dma/stm32/stm32-dmamux.c | 18 ++++++++++++------
  1 file changed, 12 insertions(+), 6 deletions(-)
drivers/dma/stm32/stm32-dmamux.c +12 -6
index 8d77e2a7939a..791179760782 100644
@@ -90,23 +90,25 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  	struct stm32_dmamux_data *dmamux = platform_get_drvdata(pdev);
  	struct stm32_dmamux *mux;
  	u32 i, min, max;
-	int ret;
+	int ret = -EINVAL;
  	unsigned long flags;
 
  	if (dma_spec->args_count != 3) {
  		dev_err(&pdev->dev, "invalid number of dma mux args\n");
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	if (dma_spec->args[0] > dmamux->dmamux_requests) {
  		dev_err(&pdev->dev, "invalid mux request number: %d\n",
  			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto err_put_pdev;
  	}
 
  	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
-	if (!mux)
-		return ERR_PTR(-ENOMEM);
+	if (!mux) {
+		ret = -ENOMEM;
+		goto err_put_pdev;
+	}
 
  	spin_lock_irqsave(&dmamux->lock, flags);
  	mux->chan_id = find_first_zero_bit(dmamux->dma_inuse,
@@ -133,7 +135,6 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1);
  	if (!dma_spec->np) {
  		dev_err(&pdev->dev, "can't get dma master\n");
-		ret = -EINVAL;
  		goto error;
  	}
 
@@ -160,6 +161,8 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  	dev_dbg(&pdev->dev, "Mapping DMAMUX(%u) to DMA%u(%u)\n",
  		mux->request, mux->master, mux->chan_id);
 
+	put_device(&pdev->dev);
+
  	return mux;
 
  error:
@@ -167,6 +170,9 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
  error_chan_id:
  	kfree(mux);
+err_put_pdev:
+	put_device(&pdev->dev);
+
  	return ERR_PTR(ret);
  }
 
#24 lore raw

Re: [PATCH 09/15] dmaengine: stm32: dmamux: fix device leak on route allocation

Quoted 7 lines · Amelie Delaunay
Quoted 6 lines · Johan Hovold

Make sure to drop the reference taken when looking up the DMA mux platform device during route allocation.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Quoted 6 lines
Quoted 4 lines
Fixes df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
Cc Pierre-Yves MORDRET <[email protected]>

Thanks for reviewing.

Johan

#25 lore raw

PATCH 10/15 dmaengine: stm32: dmamux: fix OF node leak on route allocation failure

In reply to Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

Fixes df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
Cc Pierre-Yves MORDRET <[email protected]>
---
 drivers/dma/stm32/stm32-dmamux.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/stm32/stm32-dmamux.c +3 -1
index 791179760782..2bd218dbabbb 100644
@@ -143,7 +143,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0) {
 		spin_unlock_irqrestore(&dmamux->lock, flags);
-		goto error;
+		goto err_put_dma_spec_np;
 	}
 	spin_unlock_irqrestore(&dmamux->lock, flags);
 
@@ -165,6 +165,8 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 	return mux;
 
+err_put_dma_spec_np:
+	of_node_put(dma_spec->np);
 error:
 	clear_bit(mux->chan_id, dmamux->dma_inuse);
 
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 10/15
#26 lore raw

Re: [PATCH 10/15] dmaengine: stm32: dmamux: fix OF node leak on route allocation failure

Quoted 7 lines · Johan Hovold

Make sure to drop the reference taken to the DMA master OF node also on late route allocation failures.

Fixes df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
Cc Pierre-Yves MORDRET <[email protected]>
Quoted 26 lines
---
  drivers/dma/stm32/stm32-dmamux.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/stm32/stm32-dmamux.c +3 -1
index 791179760782..2bd218dbabbb 100644
@@ -143,7 +143,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  	ret = pm_runtime_resume_and_get(&pdev->dev);
  	if (ret < 0) {
  		spin_unlock_irqrestore(&dmamux->lock, flags);
-		goto error;
+		goto err_put_dma_spec_np;
  	}
  	spin_unlock_irqrestore(&dmamux->lock, flags);
 
@@ -165,6 +165,8 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
  	return mux;
 
+err_put_dma_spec_np:
+	of_node_put(dma_spec->np);
  error:
  	clear_bit(mux->chan_id, dmamux->dma_inuse);
 
#27 lore raw

PATCH 11/15 dmaengine: stm32: dmamux: clean up route allocation error labels

In reply to Johan Hovold

Error labels should be named after what they do (and not after wherefrom they are jumped to).

---
 drivers/dma/stm32/stm32-dmamux.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/dma/stm32/stm32-dmamux.c +4 -5
index 2bd218dbabbb..db13498b9c9f 100644
@@ -118,7 +118,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 		spin_unlock_irqrestore(&dmamux->lock, flags);
 		dev_err(&pdev->dev, "Run out of free DMA requests\n");
 		ret = -ENOMEM;
-		goto error_chan_id;
+		goto err_free_mux;
 	}
 	set_bit(mux->chan_id, dmamux->dma_inuse);
 	spin_unlock_irqrestore(&dmamux->lock, flags);
@@ -135,7 +135,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "can't get dma master\n");
-		goto error;
+		goto err_clear_inuse;
 	}
 
 	/* Set dma request */
@@ -167,10 +167,9 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
 err_put_dma_spec_np:
 	of_node_put(dma_spec->np);
-error:
+err_clear_inuse:
 	clear_bit(mux->chan_id, dmamux->dma_inuse);
-
-error_chan_id:
+err_free_mux:
 	kfree(mux);
 err_put_pdev:
 	put_device(&pdev->dev);
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 11/15
#28 lore raw

Re: [PATCH 11/15] dmaengine: stm32: dmamux: clean up route allocation error labels

Quoted 4 lines · Johan Hovold

Error labels should be named after what they do (and not after wherefrom they are jumped to).

Quoted 39 lines
---
  drivers/dma/stm32/stm32-dmamux.c | 9 ++++-----
  1 file changed, 4 insertions(+), 5 deletions(-)
drivers/dma/stm32/stm32-dmamux.c +4 -5
index 2bd218dbabbb..db13498b9c9f 100644
@@ -118,7 +118,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  		spin_unlock_irqrestore(&dmamux->lock, flags);
  		dev_err(&pdev->dev, "Run out of free DMA requests\n");
  		ret = -ENOMEM;
-		goto error_chan_id;
+		goto err_free_mux;
  	}
  	set_bit(mux->chan_id, dmamux->dma_inuse);
  	spin_unlock_irqrestore(&dmamux->lock, flags);
@@ -135,7 +135,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1);
  	if (!dma_spec->np) {
  		dev_err(&pdev->dev, "can't get dma master\n");
-		goto error;
+		goto err_clear_inuse;
  	}
 
  	/* Set dma request */
@@ -167,10 +167,9 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
  err_put_dma_spec_np:
  	of_node_put(dma_spec->np);
-error:
+err_clear_inuse:
  	clear_bit(mux->chan_id, dmamux->dma_inuse);
-
-error_chan_id:
+err_free_mux:
  	kfree(mux);
  err_put_pdev:
  	put_device(&pdev->dev);
#29 lore raw

PATCH 12/15 dmaengine: ti: dma-crossbar: fix device leak on dra7x route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the crossbar platform device during dra7x route allocation.

Note that commit 615a4bfc426e ("dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate") fixed the leak in the error paths but the reference is still leaking on successful allocation.

Fixes a074ae38f859 ("dmaengine: Add driver for TI DMA crossbar on DRA7x")
Fixes 615a4bfc426e ("dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate")
Cc [email protected] # 4.2: 615a4bfc426e
Cc Peter Ujfalusi <[email protected]>
Cc Miaoqian Lin <[email protected]>
---
 drivers/dma/ti/dma-crossbar.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/dma/ti/dma-crossbar.c +2 -0
index 7f17ee87a6dc..e52b0e139900 100644
@@ -288,6 +288,8 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
 
 	ti_dra7_xbar_write(xbar->iomem, map->xbar_out, map->xbar_in);
 
+	put_device(&pdev->dev);
+
 	return map;
 }
 
Signature · 1 line
2.51.0
#30 lore raw

PATCH 13/15 dmaengine: ti: dma-crossbar: fix device leak on am335x route allocation

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the crossbar platform device during am335x route allocation.

Fixes 42dbdcc6bf96 ("dmaengine: ti-dma-crossbar: Add support for crossbar on AM33xx/AM43xx")
Cc Peter Ujfalusi <[email protected]>
---
 drivers/dma/ti/dma-crossbar.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/dma/ti/dma-crossbar.c +10 -6
index e52b0e139900..ff05b150ad37 100644
@@ -79,34 +79,35 @@ static void *ti_am335x_xbar_route_allocate(struct of_phandle_args *dma_spec,
 {
 	struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
 	struct ti_am335x_xbar_data *xbar = platform_get_drvdata(pdev);
-	struct ti_am335x_xbar_map *map;
+	struct ti_am335x_xbar_map *map = ERR_PTR(-EINVAL);
 
 	if (dma_spec->args_count != 3)
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 
 	if (dma_spec->args[2] >= xbar->xbar_events) {
 		dev_err(&pdev->dev, "Invalid XBAR event number: %d\n",
 			dma_spec->args[2]);
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 	}
 
 	if (dma_spec->args[0] >= xbar->dma_requests) {
 		dev_err(&pdev->dev, "Invalid DMA request line number: %d\n",
 			dma_spec->args[0]);
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 	}
 
 	/* The of_node_put() will be done in the core for the node */
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "Can't get DMA master\n");
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 	}
 
 	map = kzalloc(sizeof(*map), GFP_KERNEL);
 	if (!map) {
 		of_node_put(dma_spec->np);
-		return ERR_PTR(-ENOMEM);
+		map = ERR_PTR(-ENOMEM);
+		goto out_put_pdev;
 	}
 
 	map->dma_line = (u16)dma_spec->args[0];
@@ -120,6 +121,9 @@ static void *ti_am335x_xbar_route_allocate(struct of_phandle_args *dma_spec,
 
 	ti_am335x_xbar_write(xbar->iomem, map->dma_line, map->mux_val);
 
+out_put_pdev:
+	put_device(&pdev->dev);
+
 	return map;
 }
 
Signature · 1 line
2.51.0
#31 lore raw

PATCH 14/15 dmaengine: ti: dma-crossbar: clean up dra7x route allocation error paths

In reply to Johan Hovold

Use a common exit path to drop the cross platform device reference on errors for consistency with am335x.

---
 drivers/dma/ti/dma-crossbar.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/dma/ti/dma-crossbar.c +8 -9
index ff05b150ad37..e04077d542d2 100644
@@ -245,28 +245,26 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
 {
 	struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
 	struct ti_dra7_xbar_data *xbar = platform_get_drvdata(pdev);
-	struct ti_dra7_xbar_map *map;
+	struct ti_dra7_xbar_map *map = ERR_PTR(-EINVAL);
 
 	if (dma_spec->args[0] >= xbar->xbar_requests) {
 		dev_err(&pdev->dev, "Invalid XBAR request number: %d\n",
 			dma_spec->args[0]);
-		put_device(&pdev->dev);
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 	}
 
 	/* The of_node_put() will be done in the core for the node */
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "Can't get DMA master\n");
-		put_device(&pdev->dev);
-		return ERR_PTR(-EINVAL);
+		goto out_put_pdev;
 	}
 
 	map = kzalloc(sizeof(*map), GFP_KERNEL);
 	if (!map) {
 		of_node_put(dma_spec->np);
-		put_device(&pdev->dev);
-		return ERR_PTR(-ENOMEM);
+		map = ERR_PTR(-ENOMEM);
+		goto out_put_pdev;
 	}
 
 	mutex_lock(&xbar->mutex);
@@ -277,8 +275,8 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
 		dev_err(&pdev->dev, "Run out of free DMA requests\n");
 		kfree(map);
 		of_node_put(dma_spec->np);
-		put_device(&pdev->dev);
-		return ERR_PTR(-ENOMEM);
+		map = ERR_PTR(-ENOMEM);
+		goto out_put_pdev;
 	}
 	set_bit(map->xbar_out, xbar->dma_inuse);
 	mutex_unlock(&xbar->mutex);
@@ -292,6 +290,7 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
 
 	ti_dra7_xbar_write(xbar->iomem, map->xbar_out, map->xbar_in);
 
+out_put_pdev:
 	put_device(&pdev->dev);
 
 	return map;
Signature · 1 line
2.51.0
#32 lore raw

PATCH 15/15 dmaengine: ti: k3-udma: fix device leak on udma lookup

In reply to Johan Hovold

Make sure to drop the reference taken when looking up the UDMA platform device.

Note that holding a reference to a platform device does not prevent its driver data from going away so there is no point in keeping the reference after the lookup helper returns.

Fixes d70241913413 ("dmaengine: ti: k3-udma: Add glue layer for non DMAengine users")
Fixes 1438cde8fe9c ("dmaengine: ti: k3-udma: add missing put_device() call in of_xudma_dev_get()")
Cc [email protected] # 5.6: 1438cde8fe9c
Cc Grygorii Strashko <[email protected]>
Cc Yu Kuai <[email protected]>
---
 drivers/dma/ti/k3-udma-private.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/ti/k3-udma-private.c +1 -1
index 05228bf00033..624360423ef1 100644
@@ -42,9 +42,9 @@ struct udma_dev *of_xudma_dev_get(struct device_node *np, const char *property)
 	}
 
 	ud = platform_get_drvdata(pdev);
+	put_device(&pdev->dev);
 	if (!ud) {
 		pr_debug("UDMA has not been probed\n");
-		put_device(&pdev->dev);
 		return ERR_PTR(-EPROBE_DEFER);
 	}
 
Signature · 1 line
2.51.0
maintainer Applied
#33 lore raw
In reply to Johan Hovold
Quoted 8 lines · Johan Hovold

The dmaengine drivers pretty consistently failed to release references taken when looking up devices using of_find_device_by_node() and similar helpers.

Included are also two OF node leak fixes and a couple of related cleanups.

[...]

Applied, thanks!

[01/15] dmaengine: at_hdmac: fix device leak on of_dma_xlate()

        commit: 9324a4dfc4b82ba6ac71d007763b3a34a72ebd70
[02/15] dmaengine: bcm-sba-raid: fix device leak on probe
        commit: 8d5ac0087d5d325bda6c03fe0aecce348b8054d5
[03/15] dmaengine: cv1800b-dmamux: fix device leak on route allocation
        commit: 1941fa42d218cb26eca6cf8ce7443ed4f3849c5a
[04/15] dmaengine: dw: dmamux: fix OF node leak on route allocation failure
        commit: 43cc76e43f8e0be64358945edd6c14f7a9fc39a8
[05/15] dmaengine: idxd: fix device leaks on compat bind and unbind
        commit: 91b3d5a62deaa9f41d272ae0eea10508553f990d
[06/15] dmaengine: lpc18xx-dmamux: fix device leak on route allocation
        commit: 216b4a61613715b254e52bd3079aa44ad8f21734
[07/15] dmaengine: lpc32xx-dmamux: fix device leak on route allocation
        commit: 8805fc665732f93e7db8fca86fa251a0c793a82b
[08/15] dmaengine: sh: rz-dmac: fix device leak on probe failure
        commit: f7e468e72ba4bd81d0dd8d8462c90dfd00791d6b
[09/15] dmaengine: stm32: dmamux: fix device leak on route allocation
        commit: cd624421eddae7bde7dc17b54968891a47b6fce7
[10/15] dmaengine: stm32: dmamux: fix OF node leak on route allocation failure
        commit: f9091986ac4181ca6457e8b2f88fdd37e18e35c4
[11/15] dmaengine: stm32: dmamux: clean up route allocation error labels
        commit: d2e17bfa4a0d57d2bbd2dfccbeaa39351abb0248
[12/15] dmaengine: ti: dma-crossbar: fix device leak on dra7x route allocation
        commit: f6ad296520f0827455f579a786ae5fb1c444a702
[13/15] dmaengine: ti: dma-crossbar: fix device leak on am335x route allocation
        commit: 430f93d80cad5f96cbfeefbf4a9240212230ba82
[14/15] dmaengine: ti: dma-crossbar: clean up dra7x route allocation error paths
        commit: da0bcd6d207d3756ff44ec2185a814728fe641b0
[15/15] dmaengine: ti: k3-udma: fix device leak on udma lookup
        commit: e5bee109658abc4edc8d57c8545c79f130df1b87

Best regards,

Signature · 1 line
~Vinod
maintainer Applied
#34 lore raw
In reply to Johan Hovold
Quoted 8 lines · Johan Hovold

The dmaengine drivers pretty consistently failed to release references taken when looking up devices using of_find_device_by_node() and similar helpers.

Included are also two OF node leak fixes and a couple of related cleanups.

[...]

Applied, thanks!

[01/15] dmaengine: at_hdmac: fix device leak on of_dma_xlate()

        commit: b9074b2d7a230b6e28caa23165e9d8bc0677d333
[02/15] dmaengine: bcm-sba-raid: fix device leak on probe
        commit: 7c3a46ebf15a9796b763a54272407fdbf945bed8
[03/15] dmaengine: cv1800b-dmamux: fix device leak on route allocation
        commit: 7bb7d696e0361bbfc1411462c784998cca0afcbb
[04/15] dmaengine: dw: dmamux: fix OF node leak on route allocation failure
        commit: ec25e60f9f95464aa11411db31d0906b3fb7b9f2
[05/15] dmaengine: idxd: fix device leaks on compat bind and unbind
        commit: 799900f01792cf8b525a44764f065f83fcafd468
[06/15] dmaengine: lpc18xx-dmamux: fix device leak on route allocation
        commit: d4d63059dee7e7cae0c4d9a532ed558bc90efb55
[07/15] dmaengine: lpc32xx-dmamux: fix device leak on route allocation
        commit: d9847e6d1d91462890ba297f7888fa598d47e76e
[08/15] dmaengine: sh: rz-dmac: fix device leak on probe failure
        commit: 9fb490323997dcb6f749cd2660a17a39854600cd
[09/15] dmaengine: stm32: dmamux: fix device leak on route allocation
        commit: dd6e4943889fb354efa3f700e42739da9bddb6ef
[10/15] dmaengine: stm32: dmamux: fix OF node leak on route allocation failure
        commit: b1b590a590af13ded598e70f0b72bc1e515787a1
[11/15] dmaengine: stm32: dmamux: clean up route allocation error labels
        commit: 10bf494fd77b34d0749e098c939f85abf52801d1
[12/15] dmaengine: ti: dma-crossbar: fix device leak on dra7x route allocation
        commit: dc7e44db01fc2498644e3106db3e62a9883a93d5
[13/15] dmaengine: ti: dma-crossbar: fix device leak on am335x route allocation
        commit: 4fc17b1c6d2e04ad13fd6c21cfbac68043ec03f9
[14/15] dmaengine: ti: dma-crossbar: clean up dra7x route allocation error paths
        commit: 646ff780338bd7305c9f2fdeb418fdb01623a71c
[15/15] dmaengine: ti: k3-udma: fix device leak on udma lookup
        commit: 430f7803b69cd5e5694e5dfc884c6628870af36e

Best regards,

Signature · 1 line
~Vinod