USB: dwc3: qcom: fix ACPI platform device leak
authorJohan Hovold <johan+linaro@kernel.org>
Fri, 17 Nov 2023 17:36:50 +0000 (18:36 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 3 Dec 2023 06:33:06 +0000 (07:33 +0100)
[ Upstream commit 9cf87666fc6e08572341fe08ecd909935998fbbd ]

Make sure to free the "urs" platform device, which is created for some
ACPI platforms, on probe errors and on driver unbind.

Compile-tested only.

Fixes: c25c210f590e ("usb: dwc3: qcom: add URS Host support for sdm845 ACPI boot")
Cc: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Acked-by: Andrew Halaney <ahalaney@redhat.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Link: https://lore.kernel.org/r/20231117173650.21161-4-johan+linaro@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/dwc3/dwc3-qcom.c

index 00c3021..d6c81aa 100644 (file)
@@ -767,9 +767,9 @@ node_put:
        return ret;
 }
 
-static struct platform_device *
-dwc3_qcom_create_urs_usb_platdev(struct device *dev)
+static struct platform_device *dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 {
+       struct platform_device *urs_usb = NULL;
        struct fwnode_handle *fwh;
        struct acpi_device *adev;
        char name[8];
@@ -789,9 +789,26 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 
        adev = to_acpi_device_node(fwh);
        if (!adev)
-               return NULL;
+               goto err_put_handle;
+
+       urs_usb = acpi_create_platform_device(adev, NULL);
+       if (IS_ERR_OR_NULL(urs_usb))
+               goto err_put_handle;
+
+       return urs_usb;
 
-       return acpi_create_platform_device(adev, NULL);
+err_put_handle:
+       fwnode_handle_put(fwh);
+
+       return urs_usb;
+}
+
+static void dwc3_qcom_destroy_urs_usb_platdev(struct platform_device *urs_usb)
+{
+       struct fwnode_handle *fwh = urs_usb->dev.fwnode;
+
+       platform_device_unregister(urs_usb);
+       fwnode_handle_put(fwh);
 }
 
 static int dwc3_qcom_probe(struct platform_device *pdev)
@@ -875,13 +892,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
        qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
        if (IS_ERR(qcom->qscratch_base)) {
                ret = PTR_ERR(qcom->qscratch_base);
-               goto clk_disable;
+               goto free_urs;
        }
 
        ret = dwc3_qcom_setup_irq(pdev);
        if (ret) {
                dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
-               goto clk_disable;
+               goto free_urs;
        }
 
        /*
@@ -900,7 +917,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
 
        if (ret) {
                dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
-               goto clk_disable;
+               goto free_urs;
        }
 
        ret = dwc3_qcom_interconnect_init(qcom);
@@ -937,6 +954,9 @@ depopulate:
        else
                platform_device_del(qcom->dwc3);
        platform_device_put(qcom->dwc3);
+free_urs:
+       if (qcom->urs_usb)
+               dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
 clk_disable:
        for (i = qcom->num_clocks - 1; i >= 0; i--) {
                clk_disable_unprepare(qcom->clks[i]);
@@ -962,6 +982,9 @@ static void dwc3_qcom_remove(struct platform_device *pdev)
                platform_device_del(qcom->dwc3);
        platform_device_put(qcom->dwc3);
 
+       if (qcom->urs_usb)
+               dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
+
        for (i = qcom->num_clocks - 1; i >= 0; i--) {
                clk_disable_unprepare(qcom->clks[i]);
                clk_put(qcom->clks[i]);