From 74ce8c4549f4a4980de146c708cc87eb8e34b309 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:28:47 -0800 Subject: [PATCH] --- yaml --- r: 41202 b: refs/heads/master c: c67334fbdfbba533af767610cf3fde8a49710e62 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/base/platform.c | 48 +++++++++++++++++++++++++++ trunk/include/linux/platform_device.h | 6 ++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 76374b2597c1..51e86df15166 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: acf02d23b96efa92e7cff05987122ceeb37dd075 +refs/heads/master: c67334fbdfbba533af767610cf3fde8a49710e62 diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index 940ce41f1887..d1df4a087924 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev) return drv->probe(dev); } +static int platform_drv_probe_fail(struct device *_dev) +{ + return -ENXIO; +} + static int platform_drv_remove(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); @@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv) } EXPORT_SYMBOL_GPL(platform_driver_unregister); +/** + * platform_driver_probe - register driver for non-hotpluggable device + * @drv: platform driver structure + * @probe: the driver probe routine, probably from an __init section + * + * Use this instead of platform_driver_register() when you know the device + * is not hotpluggable and has already been registered, and you want to + * remove its run-once probe() infrastructure from memory after the driver + * has bound to the device. + * + * One typical use for this would be with drivers for controllers integrated + * into system-on-chip processors, where the controller devices have been + * configured as part of board setup. + * + * Returns zero if the driver registered and bound to a device, else returns + * a negative error code and with the driver not registered. + */ +int platform_driver_probe(struct platform_driver *drv, + int (*probe)(struct platform_device *)) +{ + int retval, code; + + /* temporary section violation during probe() */ + drv->probe = probe; + retval = code = platform_driver_register(drv); + + /* 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(&platform_bus_type.klist_drivers.k_lock); + drv->probe = NULL; + if (code == 0 && list_empty(&drv->driver.klist_devices.k_list)) + retval = -ENODEV; + drv->driver.probe = platform_drv_probe_fail; + spin_unlock(&platform_bus_type.klist_drivers.k_lock); + + if (code != retval) + platform_driver_unregister(drv); + return retval; +} +EXPORT_SYMBOL_GPL(platform_driver_probe); /* modalias support enables more hands-off userspace setup: * (a) environment variable lets new-style hotplug events work once system is diff --git a/trunk/include/linux/platform_device.h b/trunk/include/linux/platform_device.h index 29cd6dee13db..20f47b81d3fa 100644 --- a/trunk/include/linux/platform_device.h +++ b/trunk/include/linux/platform_device.h @@ -58,6 +58,12 @@ struct platform_driver { extern int platform_driver_register(struct platform_driver *); extern void platform_driver_unregister(struct platform_driver *); +/* non-hotpluggable platform devices may use this so that probe() and + * its support may live in __init sections, conserving runtime memory. + */ +extern int platform_driver_probe(struct platform_driver *driver, + int (*probe)(struct platform_device *)); + #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))