perf/dwc_pcie: fix some unreleased resources
authorYunhui Cui <cuiyunhui@bytedance.com>
Thu, 20 Feb 2025 12:17:15 +0000 (20:17 +0800)
committerWill Deacon <will@kernel.org>
Sat, 1 Mar 2025 06:12:36 +0000 (06:12 +0000)
Release leaked resources, such as plat_dev and dev_info.

Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
Link: https://lore.kernel.org/r/20250220121716.50324-2-cuiyunhui@bytedance.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/perf/dwc_pcie_pmu.c

index cccecae9823f6aa6bb98e438713a1386b7f055d9..19fa2ba8dd6704ec12e57644c96f909b606c8601 100644 (file)
@@ -572,8 +572,10 @@ static int dwc_pcie_register_dev(struct pci_dev *pdev)
                return PTR_ERR(plat_dev);
 
        dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
-       if (!dev_info)
+       if (!dev_info) {
+               platform_device_unregister(plat_dev);
                return -ENOMEM;
+       }
 
        /* Cache platform device to handle pci device hotplug */
        dev_info->plat_dev = plat_dev;
@@ -730,6 +732,15 @@ static struct platform_driver dwc_pcie_pmu_driver = {
        .driver = {.name = "dwc_pcie_pmu",},
 };
 
+static void dwc_pcie_cleanup_devices(void)
+{
+       struct dwc_pcie_dev_info *dev_info, *tmp;
+
+       list_for_each_entry_safe(dev_info, tmp, &dwc_pcie_dev_info_head, dev_node) {
+               dwc_pcie_unregister_dev(dev_info);
+       }
+}
+
 static int __init dwc_pcie_pmu_init(void)
 {
        struct pci_dev *pdev = NULL;
@@ -742,7 +753,7 @@ static int __init dwc_pcie_pmu_init(void)
                ret = dwc_pcie_register_dev(pdev);
                if (ret) {
                        pci_dev_put(pdev);
-                       return ret;
+                       goto err_cleanup;
                }
        }
 
@@ -751,35 +762,35 @@ static int __init dwc_pcie_pmu_init(void)
                                      dwc_pcie_pmu_online_cpu,
                                      dwc_pcie_pmu_offline_cpu);
        if (ret < 0)
-               return ret;
+               goto err_cleanup;
 
        dwc_pcie_pmu_hp_state = ret;
 
        ret = platform_driver_register(&dwc_pcie_pmu_driver);
        if (ret)
-               goto platform_driver_register_err;
+               goto err_remove_cpuhp;
 
        ret = bus_register_notifier(&pci_bus_type, &dwc_pcie_pmu_nb);
        if (ret)
-               goto platform_driver_register_err;
+               goto err_unregister_driver;
        notify = true;
 
        return 0;
 
-platform_driver_register_err:
+err_unregister_driver:
+       platform_driver_unregister(&dwc_pcie_pmu_driver);
+err_remove_cpuhp:
        cpuhp_remove_multi_state(dwc_pcie_pmu_hp_state);
-
+err_cleanup:
+       dwc_pcie_cleanup_devices();
        return ret;
 }
 
 static void __exit dwc_pcie_pmu_exit(void)
 {
-       struct dwc_pcie_dev_info *dev_info, *tmp;
-
        if (notify)
                bus_unregister_notifier(&pci_bus_type, &dwc_pcie_pmu_nb);
-       list_for_each_entry_safe(dev_info, tmp, &dwc_pcie_dev_info_head, dev_node)
-               dwc_pcie_unregister_dev(dev_info);
+       dwc_pcie_cleanup_devices();
        platform_driver_unregister(&dwc_pcie_pmu_driver);
        cpuhp_remove_multi_state(dwc_pcie_pmu_hp_state);
 }