Commit df0cca21 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

driver core: add support for calling /sbin/hotplug when classes are found and...

driver core: add support for calling /sbin/hotplug when classes are found and removed from the system.
parent be75e771
......@@ -54,10 +54,15 @@ extern void interface_remove(struct device_class *, struct device *);
#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;
}
#endif
......@@ -84,7 +84,8 @@ int devclass_add_device(struct device * dev)
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 @@ void devclass_remove_device(struct device * dev)
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);
......
......@@ -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_hotplug (struct device *dev, const char *action)
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 @@ int dev_hotplug (struct device *dev, const char *action)
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,10 +99,9 @@ int dev_hotplug (struct device *dev, const char *action)
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,
retval = hotplug (dev, &envp[i], NUM_ENVP - i, scratch,
BUFFER_SIZE - (scratch - buffer));
if (retval) {
pr_debug ("%s - hotplug() returned %d\n",
......@@ -124,3 +123,42 @@ int dev_hotplug (struct device *dev, const char *action)
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);
}
......@@ -187,6 +187,8 @@ struct device_class {
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 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment