mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
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 commitsd0243bbd5d
("drivers core: Free dma_range_map when driver probe failed") andd8f7a5484f
("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>
This commit is contained in:
parent
5bff9632b5
commit
9ad307213f
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user