Skip to contentSkip to conversation

USB: fix device leaks at unbind

PATCH In review Johan Hovold 3 participants 9 messages Jul 24, 2025 – Jul 30, 2025

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

cover USB: fix device leaks at unbind

This series fixes a number of device leaks after failure to drop the reference taken by of_find_device_by_node().

Included is also a related clean up of the omap driver.

Note that these have only been compile tested.

Johan

Johan Hovold (5):
usb: dwc3: imx8mp: fix device leak at unbind
usb: dwc3: meson-g12a: fix device leaks at unbind
usb: gadget: udc: renesas_usb3: fix device leak at unbind
usb: musb: omap2430: fix device leak at unbind
usb: musb: omap2430: clean up probe error handling

 drivers/usb/dwc3/dwc3-imx8mp.c        |  7 ++++-
 drivers/usb/dwc3/dwc3-meson-g12a.c    |  3 +++
 drivers/usb/gadget/udc/renesas_usb3.c |  1 +
 drivers/usb/musb/omap2430.c           | 37 ++++++++++++++-------------
 4 files changed, 29 insertions(+), 19 deletions(-)
Signature · 1 line
2.49.1
#1 lore raw

PATCH 1/5 usb: dwc3: imx8mp: fix device leak at unbind

Make sure to drop the reference to the dwc3 device taken by of_find_device_by_node() on probe errors and on driver unbind.

Fixes 6dd2565989b4 ("usb: dwc3: add imx8mp dwc3 glue layer driver")
Cc Li Jun <[email protected]>
---
 drivers/usb/dwc3/dwc3-imx8mp.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-imx8mp.c +6 -1
index 3edc5aca76f9..bce6af82f54c 100644
@@ -244,7 +244,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
 					IRQF_ONESHOT, dev_name(dev), dwc3_imx);
 	if (err) {
 		dev_err(dev, "failed to request IRQ #%d --> %d\n", irq, err);
-		goto depopulate;
+		goto put_dwc3;
 	}
 
 	device_set_wakeup_capable(dev, true);
@@ -252,6 +252,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
 
 	return 0;
 
+put_dwc3:
+	put_device(&dwc3_imx->dwc3->dev);
 depopulate:
 	of_platform_depopulate(dev);
 remove_swnode:
@@ -265,8 +267,11 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
 
 static void dwc3_imx8mp_remove(struct platform_device *pdev)
 {
+	struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev);
 	struct device *dev = &pdev->dev;
 
+	put_device(&dwc3_imx->dwc3->dev);
+
 	pm_runtime_get_sync(dev);
 	of_platform_depopulate(dev);
 	device_remove_software_node(dev);
Signature · 1 line
2.49.1
#2 lore raw

PATCH 2/5 usb: dwc3: meson-g12a: fix device leaks at unbind

In reply to Johan Hovold

Make sure to drop the references taken to the child devices by of_find_device_by_node() during probe on driver unbind.

Fixes c99993376f72 ("usb: dwc3: Add Amlogic G12A DWC3 glue")
Cc Neil Armstrong <[email protected]>
---
 drivers/usb/dwc3/dwc3-meson-g12a.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/usb/dwc3/dwc3-meson-g12a.c +3 -0
index 7d80bf7b18b0..55e144ba8cfc 100644
@@ -837,6 +837,9 @@ static void dwc3_meson_g12a_remove(struct platform_device *pdev)
 
 	usb_role_switch_unregister(priv->role_switch);
 
+	put_device(priv->switch_desc.udc);
+	put_device(priv->switch_desc.usb2_port);
+
 	of_platform_depopulate(dev);
 
 	for (i = 0 ; i < PHY_COUNT ; ++i) {
Signature · 1 line
2.49.1
reviewer Reviewed-by on v1 2/5
#3 lore raw

Re: [PATCH 2/5] usb: dwc3: meson-g12a: fix device leaks at unbind

Quoted 8 lines · Johan Hovold

Make sure to drop the references taken to the child devices by of_find_device_by_node() during probe on driver unbind.

Fixes c99993376f72 ("usb: dwc3: Add Amlogic G12A DWC3 glue")
Cc Neil Armstrong <[email protected]>

Thank you for finding and fixing this!

#4 lore raw

PATCH 3/5 usb: gadget: udc: renesas_usb3: fix device leak at unbind

In reply to Johan Hovold

Make sure to drop the reference to the companion device taken during probe when the driver is unbound.

Fixes 39facfa01c9f ("usb: gadget: udc: renesas_usb3: Add register of usb role switch")
Cc Yoshihiro Shimoda <[email protected]>
---
 drivers/usb/gadget/udc/renesas_usb3.c | 1 +
 1 file changed, 1 insertion(+)
drivers/usb/gadget/udc/renesas_usb3.c +1 -0
index 3e4d56457597..d23b1762e0e4 100644
@@ -2657,6 +2657,7 @@ static void renesas_usb3_remove(struct platform_device *pdev)
 	struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
 
 	debugfs_remove_recursive(usb3->dentry);
+	put_device(usb3->host_dev);
 	device_remove_file(&pdev->dev, &dev_attr_role);
 
 	cancel_work_sync(&usb3->role_work);
Signature · 1 line
2.49.1
#5 lore raw

PATCH 4/5 usb: musb: omap2430: fix device leak at unbind

In reply to Johan Hovold

Make sure to drop the reference to the control device taken by of_find_device_by_node() during probe when the driver is unbound.

Fixes 8934d3e4d0e7 ("usb: musb: omap2430: Don't use omap_get_control_dev()")
Cc Roger Quadros <[email protected]>
---
 drivers/usb/musb/omap2430.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/usb/musb/omap2430.c +9 -5
index 2970967a4fd2..36f756f9b7f6 100644
@@ -400,7 +400,7 @@ static int omap2430_probe(struct platform_device *pdev)
 	ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err2;
+		goto err_put_control_otghs;
 	}
 
 	if (populate_irqs) {
@@ -413,7 +413,7 @@ static int omap2430_probe(struct platform_device *pdev)
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		if (!res) {
 			ret = -EINVAL;
-			goto err2;
+			goto err_put_control_otghs;
 		}
 
 		musb_res[i].start = res->start;
@@ -441,14 +441,14 @@ static int omap2430_probe(struct platform_device *pdev)
 		ret = platform_device_add_resources(musb, musb_res, i);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to add IRQ resources\n");
-			goto err2;
+			goto err_put_control_otghs;
 		}
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err2;
+		goto err_put_control_otghs;
 	}
 
 	pm_runtime_enable(glue->dev);
@@ -463,7 +463,9 @@ static int omap2430_probe(struct platform_device *pdev)
 
 err3:
 	pm_runtime_disable(glue->dev);
-
+err_put_control_otghs:
+	if (!IS_ERR(glue->control_otghs))
+		put_device(glue->control_otghs);
 err2:
 	platform_device_put(musb);
 
@@ -477,6 +479,8 @@ static void omap2430_remove(struct platform_device *pdev)
 
 	platform_device_unregister(glue->musb);
 	pm_runtime_disable(glue->dev);
+	if (!IS_ERR(glue->control_otghs))
+		put_device(glue->control_otghs);
 }
 
 #ifdef CONFIG_PM
Signature · 1 line
2.49.1
maintainer Reviewed-by on v1 4/5
#6 lore raw

Re: [PATCH 4/5] usb: musb: omap2430: fix device leak at unbind

Quoted 7 lines · Johan Hovold

Make sure to drop the reference to the control device taken by of_find_device_by_node() during probe when the driver is unbound.

Fixes 8934d3e4d0e7 ("usb: musb: omap2430: Don't use omap_get_control_dev()")
Cc Roger Quadros <[email protected]>
Quoted 65 lines
---
 drivers/usb/musb/omap2430.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/usb/musb/omap2430.c +9 -5
index 2970967a4fd2..36f756f9b7f6 100644
@@ -400,7 +400,7 @@ static int omap2430_probe(struct platform_device *pdev)
 	ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err2;
+		goto err_put_control_otghs;
 	}
 
 	if (populate_irqs) {
@@ -413,7 +413,7 @@ static int omap2430_probe(struct platform_device *pdev)
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		if (!res) {
 			ret = -EINVAL;
-			goto err2;
+			goto err_put_control_otghs;
 		}
 
 		musb_res[i].start = res->start;
@@ -441,14 +441,14 @@ static int omap2430_probe(struct platform_device *pdev)
 		ret = platform_device_add_resources(musb, musb_res, i);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to add IRQ resources\n");
-			goto err2;
+			goto err_put_control_otghs;
 		}
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err2;
+		goto err_put_control_otghs;
 	}
 
 	pm_runtime_enable(glue->dev);
@@ -463,7 +463,9 @@ static int omap2430_probe(struct platform_device *pdev)
 
 err3:
 	pm_runtime_disable(glue->dev);
-
+err_put_control_otghs:
+	if (!IS_ERR(glue->control_otghs))
+		put_device(glue->control_otghs);
 err2:
 	platform_device_put(musb);
 
@@ -477,6 +479,8 @@ static void omap2430_remove(struct platform_device *pdev)
 
 	platform_device_unregister(glue->musb);
 	pm_runtime_disable(glue->dev);
+	if (!IS_ERR(glue->control_otghs))
+		put_device(glue->control_otghs);
 }
 
 #ifdef CONFIG_PM
Signature · 1 line
2.49.1
#7 lore raw

PATCH 5/5 usb: musb: omap2430: clean up probe error handling

In reply to Johan Hovold

Using numbered error labels is discouraged (e.g. as it requires renumbering them when adding a new intermediate error path).

Rename the error labels after what they do.

While at it, drop the redundant platform allocation failure dev_err() as the error would already have been logged by the allocator.

---
 drivers/usb/musb/omap2430.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)
drivers/usb/musb/omap2430.c +10 -13
index 36f756f9b7f6..c35c07b7488c 100644
@@ -318,13 +318,11 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue)
-		goto err0;
+		return -ENOMEM;
 
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err0;
-	}
+	if (!musb)
+		return -ENOMEM;
 
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &omap2430_dmamask;
@@ -349,15 +347,15 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
-		goto err2;
+		goto err_put_musb;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
-		goto err2;
+		goto err_put_musb;
 
 	config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 	if (!config)
-		goto err2;
+		goto err_put_musb;
 
 	of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
 	of_property_read_u32(np, "interface-type",
@@ -380,7 +378,7 @@ static int omap2430_probe(struct platform_device *pdev)
 		if (!control_pdev) {
 			dev_err(&pdev->dev, "Failed to get control device\n");
 			ret = -EINVAL;
-			goto err2;
+			goto err_put_musb;
 		}
 		glue->control_otghs = &control_pdev->dev;
 	}
@@ -456,20 +454,19 @@ static int omap2430_probe(struct platform_device *pdev)
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err3;
+		goto err_disable_rpm;
 	}
 
 	return 0;
 
-err3:
+err_disable_rpm:
 	pm_runtime_disable(glue->dev);
 err_put_control_otghs:
 	if (!IS_ERR(glue->control_otghs))
 		put_device(glue->control_otghs);
-err2:
+err_put_musb:
 	platform_device_put(musb);
 
-err0:
 	return ret;
 }
 
Signature · 1 line
2.49.1
maintainer Reviewed-by on v1 5/5
#8 lore raw

Re: [PATCH 5/5] usb: musb: omap2430: clean up probe error handling

Quoted 9 lines · Johan Hovold

Using numbered error labels is discouraged (e.g. as it requires renumbering them when adding a new intermediate error path).

Rename the error labels after what they do.

While at it, drop the redundant platform allocation failure dev_err() as the error would already have been logged by the allocator.

Quoted 79 lines
---
 drivers/usb/musb/omap2430.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)
drivers/usb/musb/omap2430.c +10 -13
index 36f756f9b7f6..c35c07b7488c 100644
@@ -318,13 +318,11 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue)
-		goto err0;
+		return -ENOMEM;
 
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err0;
-	}
+	if (!musb)
+		return -ENOMEM;
 
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &omap2430_dmamask;
@@ -349,15 +347,15 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
-		goto err2;
+		goto err_put_musb;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
-		goto err2;
+		goto err_put_musb;
 
 	config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 	if (!config)
-		goto err2;
+		goto err_put_musb;
 
 	of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
 	of_property_read_u32(np, "interface-type",
@@ -380,7 +378,7 @@ static int omap2430_probe(struct platform_device *pdev)
 		if (!control_pdev) {
 			dev_err(&pdev->dev, "Failed to get control device\n");
 			ret = -EINVAL;
-			goto err2;
+			goto err_put_musb;
 		}
 		glue->control_otghs = &control_pdev->dev;
 	}
@@ -456,20 +454,19 @@ static int omap2430_probe(struct platform_device *pdev)
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err3;
+		goto err_disable_rpm;
 	}
 
 	return 0;
 
-err3:
+err_disable_rpm:
 	pm_runtime_disable(glue->dev);
 err_put_control_otghs:
 	if (!IS_ERR(glue->control_otghs))
 		put_device(glue->control_otghs);
-err2:
+err_put_musb:
 	platform_device_put(musb);
 
-err0:
 	return ret;
 }
 
Signature · 1 line
2.49.1