Calling pr_report_probe() after the removal is unexpected as for initcalls and probes, we print before to make hangs or crashes easier to pinpoint.
Signed-off-by: Ahmad Fatoum <[email protected]> --- drivers/base/driver.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 753e06963b16..102e7ea2c0dd 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -659,15 +659,25 @@ int dev_add_alias(struct device *dev, const char *fmt, ...) } EXPORT_SYMBOL_GPL(dev_add_alias); -bool device_remove(struct device *dev) +typedef void (*dev_remove_op_t)(struct device *dev); + +static dev_remove_op_t get_device_remove(struct device *dev) { if (dev->bus && dev->bus->remove) - dev->bus->remove(dev); + return dev->bus->remove; else if (dev->driver->remove) - dev->driver->remove(dev); + return dev->driver->remove; else - return false; /* nothing to do */ + return NULL; +} +bool device_remove(struct device *dev) +{ + dev_remove_op_t remove = get_device_remove(dev); + if (!remove) + return false; /* nothing to do */ + + remove(dev); return true; } EXPORT_SYMBOL_GPL(device_remove); @@ -677,8 +687,11 @@ static void devices_shutdown(void) struct device *dev; list_for_each_entry(dev, &active_device_list, active) { - if (device_remove(dev)) + dev_remove_op_t remove = get_device_remove(dev); + if (remove) { pr_report_probe("%*sremove-> %s\n", 1 * 4, "", dev_name(dev)); + remove(dev); + } dev->driver = NULL; } } -- 2.47.3
