ChangeSet 1.808.2.12, 2002/10/24 15:01:51-07:00, greg@kroah.com driver core: add support for calling /sbin/hotplug when classes are found and removed from the system. diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Mon Oct 28 13:54:13 2002 +++ b/drivers/base/base.h Mon Oct 28 13:54:13 2002 @@ -54,8 +54,13 @@ #ifdef CONFIG_HOTPLUG extern int dev_hotplug(struct device *dev, const char *action); +extern int class_hotplug(struct device *dev, const char *action); #else static inline int dev_hotplug(struct device *dev, const char *action) +{ + return 0; +} +static int class_hotplug(struct device *dev, const char *action) { return 0; } diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c Mon Oct 28 13:54:13 2002 +++ b/drivers/base/class.c Mon Oct 28 13:54:13 2002 @@ -84,7 +84,8 @@ interface_add(cls,dev); } - /* notify userspace (call /sbin/hotplug) here */ + /* notify userspace (call /sbin/hotplug) */ + class_hotplug (dev, "add"); up_write(&cls->rwsem); if (error) @@ -106,6 +107,10 @@ cls->name,dev->name); interface_remove(cls,dev); unenum_device(cls,dev); + + /* notify userspace (call /sbin/hotplug) */ + class_hotplug (dev, "remove"); + if (cls->remove_device) cls->remove_device(dev); up_write(&cls->rwsem); diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c --- a/drivers/base/hotplug.c Mon Oct 28 13:54:13 2002 +++ b/drivers/base/hotplug.c Mon Oct 28 13:54:13 2002 @@ -22,15 +22,21 @@ /* * hotplugging invokes what /proc/sys/kernel/hotplug says (normally - * /sbin/hotplug) when devices get added or removed. + * /sbin/hotplug) when devices or classes get added or removed. * * This invokes a user mode policy agent, typically helping to load driver * or other modules, configure the device, and more. Drivers can provide * a MODULE_DEVICE_TABLE to help with module loading subtasks. + * + * See the documentation at http://linux-hotplug.sf.net for more info. + * */ + #define BUFFER_SIZE 1024 /* should be enough memory for the env */ #define NUM_ENVP 32 /* number of env pointers */ -int dev_hotplug (struct device *dev, const char *action) + +static int do_hotplug (struct device *dev, char *argv1, const char *action, + int (* hotplug) (struct device *, char **, int, char *, int)) { char *argv [3], **envp, *buffer, *scratch; char *dev_path; @@ -39,11 +45,6 @@ int dev_length; pr_debug ("%s\n", __FUNCTION__); - if (!dev) - return -ENODEV; - - if (!dev->bus) - return -ENODEV; if (!hotplug_path [0]) return -ENODEV; @@ -82,9 +83,8 @@ strcpy (dev_path, "root"); fill_devpath (dev, dev_path, dev_length); - /* only one standardized param to hotplug command: the bus name */ argv [0] = hotplug_path; - argv [1] = dev->bus->name; + argv [1] = argv1; argv [2] = 0; /* minimal command environment */ @@ -99,11 +99,10 @@ envp [i++] = scratch; scratch += sprintf (scratch, "DEVPATH=%s", dev_path) + 1; - if (dev->bus->hotplug) { + if (hotplug) { /* have the bus specific function add its stuff */ - retval = dev->bus->hotplug (dev, &envp[i], NUM_ENVP - i, - scratch, - BUFFER_SIZE - (scratch - buffer)); + retval = hotplug (dev, &envp[i], NUM_ENVP - i, scratch, + BUFFER_SIZE - (scratch - buffer)); if (retval) { pr_debug ("%s - hotplug() returned %d\n", __FUNCTION__, retval); @@ -123,4 +122,43 @@ kfree (buffer); kfree (envp); return retval; +} + + +/* + * dev_hotplug - called when any device is added or removed from a bus + */ +int dev_hotplug (struct device *dev, const char *action) +{ + pr_debug ("%s\n", __FUNCTION__); + if (!dev) + return -ENODEV; + + if (!dev->bus) + return -ENODEV; + + return do_hotplug (dev, dev->bus->name, action, dev->bus->hotplug); +} + + +/* + * class_hotplug - called when a class is added or removed from a device + */ +int class_hotplug (struct device *dev, const char *action) +{ + struct device_class * cls; + + pr_debug ("%s\n", __FUNCTION__); + + if (!dev) + return -ENODEV; + + if (!dev->bus) + return -ENODEV; + + cls = get_devclass(dev->driver->devclass); + if (!cls) + return -ENODEV; + + return do_hotplug (dev, cls->name, action, cls->hotplug); } diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Mon Oct 28 13:54:13 2002 +++ b/include/linux/device.h Mon Oct 28 13:54:13 2002 @@ -187,6 +187,8 @@ int (*add_device)(struct device *); void (*remove_device)(struct device *); + int (*hotplug)(struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); }; extern int devclass_register(struct device_class *);