driver core: platform: simplify __platform_driver_probe()

__platform_driver_probe() pokes around in some bus and driver private
lists and locks in a way that is not needed at all.  The code only wants
to know if a device was bound to the driver that was registered, so walk
all devices on the bus to see if there was a match.  If there is not a
match, return an error.  This is the same logic as was originally
present, but just done in a simpler and more obvious way that is not a
layering violation.

Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Link: https://lore.kernel.org/r/20230131082459.301603-2-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2023-01-31 09:24:59 +01:00
parent b4ce0bf7ab
commit 40b3880dc2
1 changed files with 15 additions and 11 deletions

View File

@ -883,6 +883,13 @@ static int platform_probe_fail(struct platform_device *pdev)
return -ENXIO;
}
static int is_bound_to_driver(struct device *dev, void *driver)
{
if (dev->driver == driver)
return 1;
return 0;
}
/**
* __platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
@ -936,20 +943,17 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv,
if (retval)
return retval;
/*
* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
/* Force all new probes of this driver to fail */
drv->probe = platform_probe_fail;
if (list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
if (retval)
/* Walk all platform devices and see if any actually bound to this driver.
* If not, return an error as the device should have done so by now.
*/
if (!bus_for_each_dev(&platform_bus_type, NULL, &drv->driver, is_bound_to_driver)) {
retval = -ENODEV;
platform_driver_unregister(drv);
}
return retval;
}
EXPORT_SYMBOL_GPL(__platform_driver_probe);