driver core: Refactor multiple copies of device cleanup
authorRob Herring <robh@kernel.org>
Wed, 23 Feb 2022 22:52:56 +0000 (16:52 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Mar 2022 13:27:26 +0000 (14:27 +0100)
There are 3 copies of the same device cleanup code used for probe failure,
testing re-probing, and device unbinding. Changes to this code often miss
at least one of the copies of the code. See commits d0243bbd5dd3 ("drivers
core: Free dma_range_map when driver probe failed") and d8f7a5484f21
("driver core: Free DMA range map when device is released") for example.

Let's refactor the code to its own function.

Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20220223225257.1681968-2-robh@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/dd.c

index ce30f34..86e2309 100644 (file)
@@ -506,6 +506,19 @@ static ssize_t state_synced_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(state_synced);
 
+static void device_unbind_cleanup(struct device *dev)
+{
+       devres_release_all(dev);
+       arch_teardown_dma_ops(dev);
+       kfree(dev->dma_range_map);
+       dev->dma_range_map = NULL;
+       dev->driver = NULL;
+       dev_set_drvdata(dev, NULL);
+       if (dev->pm_domain && dev->pm_domain->dismiss)
+               dev->pm_domain->dismiss(dev);
+       pm_runtime_reinit(dev);
+       dev_pm_set_driver_flags(dev, 0);
+}
 
 static int call_driver_probe(struct device *dev, struct device_driver *drv)
 {
@@ -628,16 +641,8 @@ re_probe:
                else if (drv->remove)
                        drv->remove(dev);
 
-               devres_release_all(dev);
-               arch_teardown_dma_ops(dev);
-               kfree(dev->dma_range_map);
-               dev->dma_range_map = NULL;
                driver_sysfs_remove(dev);
-               dev->driver = NULL;
-               dev_set_drvdata(dev, NULL);
-               if (dev->pm_domain && dev->pm_domain->dismiss)
-                       dev->pm_domain->dismiss(dev);
-               pm_runtime_reinit(dev);
+               device_unbind_cleanup(dev);
 
                goto re_probe;
        }
@@ -667,16 +672,7 @@ sysfs_failed:
                                             BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
 pinctrl_bind_failed:
        device_links_no_driver(dev);
-       devres_release_all(dev);
-       arch_teardown_dma_ops(dev);
-       kfree(dev->dma_range_map);
-       dev->dma_range_map = NULL;
-       dev->driver = NULL;
-       dev_set_drvdata(dev, NULL);
-       if (dev->pm_domain && dev->pm_domain->dismiss)
-               dev->pm_domain->dismiss(dev);
-       pm_runtime_reinit(dev);
-       dev_pm_set_driver_flags(dev, 0);
+       device_unbind_cleanup(dev);
 done:
        return ret;
 }
@@ -1209,17 +1205,7 @@ static void __device_release_driver(struct device *dev, struct device *parent)
                        drv->remove(dev);
 
                device_links_driver_cleanup(dev);
-
-               devres_release_all(dev);
-               arch_teardown_dma_ops(dev);
-               kfree(dev->dma_range_map);
-               dev->dma_range_map = NULL;
-               dev->driver = NULL;
-               dev_set_drvdata(dev, NULL);
-               if (dev->pm_domain && dev->pm_domain->dismiss)
-                       dev->pm_domain->dismiss(dev);
-               pm_runtime_reinit(dev);
-               dev_pm_set_driver_flags(dev, 0);
+               device_unbind_cleanup(dev);
 
                klist_remove(&dev->p->knode_driver);
                device_pm_check_callbacks(dev);