Commit 9ad30721 authored by Rob Herring's avatar Rob Herring Committed by Greg Kroah-Hartman
Browse files

driver core: Refactor multiple copies of device cleanup



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 d0243bbd ("drivers
core: Free dma_range_map when driver probe failed") and d8f7a548
("driver core: Free DMA range map when device is released") for example.

Let's refactor the code to its own function.

Signed-off-by: default avatarRob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20220223225257.1681968-2-robh@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5bff9632
Loading
Loading
Loading
Loading
+16 −30
Original line number Diff line number Diff line
@@ -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 @@ static int really_probe(struct device *dev, struct device_driver *drv)
		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 @@ static int really_probe(struct device *dev, struct device_driver *drv)
					     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);