Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
Trivial manual merge fixup for usb_find_interface clashes.
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
index e75d747..67a11a3 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.txt
+++ b/Documentation/powerpc/eeh-pci-error-recovery.txt
@@ -115,7 +115,7 @@
At this time, a generic EEH recovery mechanism has been implemented,
so that individual device drivers do not need to be modified to support
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
-infrastructure, and percolates events up through the hotplug/udev
+infrastructure, and percolates events up through the userspace/udev
infrastructure. Followiing is a detailed description of how this is
accomplished.
@@ -172,7 +172,7 @@
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
This last call causes the device driver for the card to be stopped,
-which causes hotplug events to go out to user space. This triggers
+which causes uevents to go out to user space. This triggers
user-space scripts that might issue commands such as "ifdown eth0"
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
hoping to give the user-space scripts enough time to complete.
@@ -258,29 +258,30 @@
calls
pci_destroy_dev (struct pci_dev *) {
calls
- device_unregister (&dev->dev) { // in /drivers/base/core.c
+ device_unregister (&dev->dev) { // in /drivers/base/core.c
calls
- device_del(struct device * dev) { // in /drivers/base/core.c
+ device_del(struct device * dev) { // in /drivers/base/core.c
calls
- kobject_del() { //in /libs/kobject.c
+ kobject_del() { //in /libs/kobject.c
calls
- kobject_hotplug() { // in /libs/kobject.c
+ kobject_uevent() { // in /libs/kobject.c
calls
- kset_hotplug() { // in /lib/kobject.c
+ kset_uevent() { // in /lib/kobject.c
calls
- kset->hotplug_ops->hotplug() which is really just
+ kset->uevent_ops->uevent() // which is really just
a call to
- dev_hotplug() { // in /drivers/base/core.c
+ dev_uevent() { // in /drivers/base/core.c
calls
- dev->bus->hotplug() which is really just a call to
- pci_hotplug () { // in drivers/pci/hotplug.c
+ dev->bus->uevent() which is really just a call to
+ pci_uevent () { // in drivers/pci/hotplug.c
which prints device name, etc....
}
}
- then kset_hotplug() calls
- call_usermodehelper () with
- argv[0]=hotplug_path[] which is "/sbin/hotplug"
- --> event to userspace,
+ then kobject_uevent() sends a netlink uevent to userspace
+ --> userspace uevent
+ (during early boot, nobody listens to netlink events and
+ kobject_uevent() executes uevent_helper[], which runs the
+ event process /sbin/hotplug)
}
}
kobject_del() then calls sysfs_remove_dir(), which would
diff --git a/MAINTAINERS b/MAINTAINERS
index 1e59d39..6246b7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1480,12 +1480,6 @@
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
S: Maintained
-KERNEL EVENT LAYER (KOBJECT_UEVENT)
-P: Robert Love
-M: rml@novell.com
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
KEXEC
P: Eric Biederman
P: Randy Dunlap
diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c
index e101311..c95ec9e 100644
--- a/arch/arm/common/amba.c
+++ b/arch/arm/common/amba.c
@@ -45,7 +45,7 @@
}
#ifdef CONFIG_HOTPLUG
-static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
+static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
{
struct amba_device *pcdev = to_amba_device(dev);
@@ -58,7 +58,7 @@
return 0;
}
#else
-#define amba_hotplug NULL
+#define amba_uevent NULL
#endif
static int amba_suspend(struct device *dev, pm_message_t state)
@@ -88,7 +88,7 @@
static struct bus_type amba_bustype = {
.name = "amba",
.match = amba_match,
- .hotplug = amba_hotplug,
+ .uevent = amba_uevent,
.suspend = amba_suspend,
.resume = amba_resume,
};
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 0d8592a..768c21d 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -65,7 +65,7 @@
}
-static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
+static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -79,7 +79,7 @@
struct bus_type tiocx_bus_type = {
.name = "tiocx",
.match = tiocx_match,
- .hotplug = tiocx_hotplug,
+ .uevent = tiocx_uevent,
};
/**
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 71a6add..13c4149 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -293,6 +293,6 @@
struct bus_type vio_bus_type = {
.name = "vio",
- .hotplug = vio_hotplug,
+ .uevent = vio_hotplug,
.match = vio_bus_match,
};
diff --git a/block/genhd.c b/block/genhd.c
index f04609d..f1ed83f 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -358,7 +358,7 @@
static ssize_t disk_uevent_store(struct gendisk * disk,
const char *buf, size_t count)
{
- kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
return count;
}
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
@@ -455,14 +455,14 @@
extern struct kobj_type ktype_part;
-static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
return ((ktype == &ktype_block) || (ktype == &ktype_part));
}
-static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -474,40 +474,40 @@
if (ktype == &ktype_block) {
disk = container_of(kobj, struct gendisk, kobj);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "MINOR=%u", disk->first_minor);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) {
disk = container_of(kobj->parent, struct gendisk, kobj);
part = container_of(kobj, struct hd_struct, kobj);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "MINOR=%u",
- disk->first_minor + part->partno);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MINOR=%u",
+ disk->first_minor + part->partno);
} else
return 0;
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
- "MAJOR=%u", disk->major);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MAJOR=%u", disk->major);
/* add physical device, backing this device */
physdev = disk->driverfs_dev;
if (physdev) {
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "PHYSDEVPATH=%s", path);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "PHYSDEVPATH=%s", path);
kfree(path);
if (physdev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s",
- physdev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s",
+ physdev->bus->name);
if (physdev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s",
- physdev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s",
+ physdev->driver->name);
}
/* terminate, set to next free slot, shrink available space */
@@ -520,13 +520,13 @@
return 0;
}
-static struct kset_hotplug_ops block_hotplug_ops = {
- .filter = block_hotplug_filter,
- .hotplug = block_hotplug,
+static struct kset_uevent_ops block_uevent_ops = {
+ .filter = block_uevent_filter,
+ .uevent = block_uevent,
};
/* declare block_subsys. */
-static decl_subsys(block, &ktype_block, &block_hotplug_ops);
+static decl_subsys(block, &ktype_block, &block_uevent_ops);
/*
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 27ec12c..b69a8ca 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -172,21 +172,21 @@
if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle);
if (!result)
- kobject_hotplug(&device->kobj,
- KOBJ_ONLINE);
+ kobject_uevent(&device->kobj,
+ KOBJ_ONLINE);
else
printk("Failed to add container\n");
}
} else {
if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
}
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
if (!acpi_bus_get_device(handle, &device) && device) {
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
}
break;
default:
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0c561c5..1278aca 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -748,7 +748,7 @@
return_VALUE(-ENODEV);
if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
- kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
+ kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
}
return_VALUE(0);
}
@@ -788,13 +788,13 @@
}
if (pr->id >= 0 && (pr->id < NR_CPUS)) {
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
break;
}
result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
- kobject_hotplug(&device->kobj, KOBJ_ONLINE);
+ kobject_uevent(&device->kobj, KOBJ_ONLINE);
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Device [%s] failed to start\n",
@@ -818,7 +818,7 @@
}
if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 31218e1..0745d20 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -78,7 +78,7 @@
.release = acpi_device_release,
};
-static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+static int namespace_uevent(struct kset *kset, struct kobject *kobj,
char **envp, int num_envp, char *buffer,
int buffer_size)
{
@@ -89,8 +89,8 @@
if (!dev->driver)
return 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "PHYSDEVDRIVER=%s", dev->driver->name))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "PHYSDEVDRIVER=%s", dev->driver->name))
return -ENOMEM;
envp[i] = NULL;
@@ -98,8 +98,8 @@
return 0;
}
-static struct kset_hotplug_ops namespace_hotplug_ops = {
- .hotplug = &namespace_hotplug,
+static struct kset_uevent_ops namespace_uevent_ops = {
+ .uevent = &namespace_uevent,
};
static struct kset acpi_namespace_kset = {
@@ -108,7 +108,7 @@
},
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
- .hotplug_ops = &namespace_hotplug_ops,
+ .uevent_ops = &namespace_uevent_ops,
};
static void acpi_device_register(struct acpi_device *device,
@@ -347,7 +347,7 @@
}
/* --------------------------------------------------------------------------
- ACPI hotplug sysfs device file support
+ ACPI sysfs device file support
-------------------------------------------------------------------------- */
static ssize_t acpi_eject_store(struct acpi_device *device,
const char *buf, size_t count);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 934149c..f0eff3d 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -19,11 +19,11 @@
If unsure say Y here.
config FW_LOADER
- tristate "Hotplug firmware loading support"
+ tristate "Userspace firmware loading support"
select HOTPLUG
---help---
This option is provided for the case where no in-kernel-tree modules
- require hotplug firmware loading support, but a module built outside
+ require userspace firmware loading support, but a module built outside
the kernel tree does.
config DEBUG_DRIVER
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa601b0..29f6af5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -152,7 +152,11 @@
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == drv) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_release_driver(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
err = count;
}
put_device(dev);
@@ -175,9 +179,13 @@
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == NULL) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
err = driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
}
put_device(dev);
put_bus(bus);
@@ -420,6 +428,26 @@
}
}
+#ifdef CONFIG_HOTPLUG
+/*
+ * Thanks to drivers making their tables __devinit, we can't allow manual
+ * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
+ */
+static void add_bind_files(struct device_driver *drv)
+{
+ driver_create_file(drv, &driver_attr_unbind);
+ driver_create_file(drv, &driver_attr_bind);
+}
+
+static void remove_bind_files(struct device_driver *drv)
+{
+ driver_remove_file(drv, &driver_attr_bind);
+ driver_remove_file(drv, &driver_attr_unbind);
+}
+#else
+static inline void add_bind_files(struct device_driver *drv) {}
+static inline void remove_bind_files(struct device_driver *drv) {}
+#endif
/**
* bus_add_driver - Add a driver to the bus.
@@ -449,8 +477,7 @@
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
- driver_create_file(drv, &driver_attr_unbind);
- driver_create_file(drv, &driver_attr_bind);
+ add_bind_files(drv);
}
return error;
}
@@ -468,8 +495,7 @@
void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
- driver_remove_file(drv, &driver_attr_bind);
- driver_remove_file(drv, &driver_attr_unbind);
+ remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv);
klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -484,8 +510,13 @@
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
- if (!dev->driver)
+ if (!dev->driver) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_attach(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
+ }
return 0;
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index db65fd0..df7fdab 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -178,7 +178,7 @@
}
/* needed to allow these devices to have parent class devices */
-static int class_device_create_hotplug(struct class_device *class_dev,
+static int class_device_create_uevent(struct class_device *class_dev,
char **envp, int num_envp,
char *buffer, int buffer_size)
{
@@ -331,7 +331,7 @@
.release = class_dev_release,
};
-static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -343,14 +343,14 @@
return 0;
}
-static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
{
struct class_device *class_dev = to_class_dev(kobj);
return class_dev->class->name;
}
-static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
@@ -365,29 +365,29 @@
struct device *dev = class_dev->dev;
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "PHYSDEVPATH=%s", path);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "PHYSDEVPATH=%s", path);
kfree(path);
if (dev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
}
if (MAJOR(class_dev->devt)) {
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MAJOR=%u", MAJOR(class_dev->devt));
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MAJOR=%u", MAJOR(class_dev->devt));
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MINOR=%u", MINOR(class_dev->devt));
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MINOR=%u", MINOR(class_dev->devt));
}
/* terminate, set to next free slot, shrink available space */
@@ -397,30 +397,30 @@
buffer = &buffer[length];
buffer_size -= length;
- if (class_dev->hotplug) {
+ if (class_dev->uevent) {
/* have the class device specific function add its stuff */
- retval = class_dev->hotplug(class_dev, envp, num_envp,
+ retval = class_dev->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
- pr_debug("class_dev->hotplug() returned %d\n", retval);
- } else if (class_dev->class->hotplug) {
+ pr_debug("class_dev->uevent() returned %d\n", retval);
+ } else if (class_dev->class->uevent) {
/* have the class specific function add its stuff */
- retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+ retval = class_dev->class->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
- pr_debug("class->hotplug() returned %d\n", retval);
+ pr_debug("class->uevent() returned %d\n", retval);
}
return retval;
}
-static struct kset_hotplug_ops class_hotplug_ops = {
- .filter = class_hotplug_filter,
- .name = class_hotplug_name,
- .hotplug = class_hotplug,
+static struct kset_uevent_ops class_uevent_ops = {
+ .filter = class_uevent_filter,
+ .name = class_uevent_name,
+ .uevent = class_uevent,
};
-static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
+static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
static int class_device_add_attrs(struct class_device * cd)
@@ -464,7 +464,7 @@
static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&class_dev->kobj, KOBJ_ADD);
return count;
}
@@ -559,7 +559,7 @@
class_name);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
if (parent_class) {
@@ -632,7 +632,7 @@
class_dev->class = cls;
class_dev->parent = parent;
class_dev->release = class_device_create_release;
- class_dev->hotplug = class_device_create_hotplug;
+ class_dev->uevent = class_device_create_uevent;
va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -674,7 +674,7 @@
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
- kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj);
class_device_put(parent_device);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8615b42..fd80599 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -90,7 +90,7 @@
};
-static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -102,14 +102,14 @@
return 0;
}
-static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
return dev->bus->name;
}
-static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct device *dev = to_dev(kobj);
@@ -119,15 +119,15 @@
/* add bus name of physical device */
if (dev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
/* add driver name of physical device */
if (dev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
@@ -136,11 +136,11 @@
buffer = &buffer[length];
buffer_size -= length;
- if (dev->bus && dev->bus->hotplug) {
+ if (dev->bus && dev->bus->uevent) {
/* have the bus specific function add its stuff */
- retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
+ retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
+ pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval);
}
}
@@ -148,16 +148,16 @@
return retval;
}
-static struct kset_hotplug_ops device_hotplug_ops = {
- .filter = dev_hotplug_filter,
- .name = dev_hotplug_name,
- .hotplug = dev_hotplug,
+static struct kset_uevent_ops device_uevent_ops = {
+ .filter = dev_uevent_filter,
+ .name = dev_uevent_name,
+ .uevent = dev_uevent,
};
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
return count;
}
@@ -165,7 +165,7 @@
* device_subsys - structure to be registered with kobject core.
*/
-decl_subsys(devices, &ktype_device, &device_hotplug_ops);
+decl_subsys(devices, &ktype_device, &device_uevent_ops);
/**
@@ -274,7 +274,7 @@
dev->uevent_attr.store = store_uevent;
device_create_file(dev, &dev->uevent_attr);
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
@@ -291,7 +291,7 @@
BusError:
device_pm_remove(dev);
PMError:
- kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
if (parent)
@@ -374,7 +374,7 @@
platform_notify_remove(dev);
bus_remove_device(dev);
device_pm_remove(dev);
- kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
if (parent)
put_device(parent);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index a958447..281d267 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -41,14 +41,14 @@
case '0':
ret = cpu_down(cpu->sysdev.id);
if (!ret)
- kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
break;
case '1':
ret = smp_prepare_cpu(cpu->sysdev.id);
if (!ret)
ret = cpu_up(cpu->sysdev.id);
if (!ret)
- kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
+ kobject_uevent(&dev->kobj, KOBJ_ONLINE);
break;
default:
ret = -EINVAL;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3b419c9..2b90501 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,8 @@
* This function returns 1 if a match is found, an error if one
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
*
- * This function must be called with @dev->sem held.
+ * This function must be called with @dev->sem held. When called
+ * for a USB interface, @dev->parent->sem must be held as well.
*/
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
@@ -123,6 +124,8 @@
*
* Returns 1 if the device was bound to a driver;
* 0 if no matching device was found; error code otherwise.
+ *
+ * When called for a USB interface, @dev->parent->sem must be held.
*/
int device_attach(struct device * dev)
{
@@ -152,10 +155,14 @@
* is an error.
*/
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
return 0;
}
@@ -181,6 +188,8 @@
* Manually detach device from driver.
*
* __device_release_driver() must be called with @dev->sem held.
+ * When called for a USB interface, @dev->parent->sem must be held
+ * as well.
*/
static void __device_release_driver(struct device * dev)
@@ -233,10 +242,14 @@
get_device(dev);
spin_unlock(&drv->klist_devices.k_lock);
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (dev->driver == drv)
__device_release_driver(dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
put_device(dev);
}
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 59dacb6..5b3d5e9 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -85,17 +85,17 @@
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_class_dev_release(struct class_device *class_dev);
-int firmware_class_hotplug(struct class_device *dev, char **envp,
+int firmware_class_uevent(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
static struct class firmware_class = {
.name = "firmware",
- .hotplug = firmware_class_hotplug,
+ .uevent = firmware_class_uevent,
.release = fw_class_dev_release,
};
int
-firmware_class_hotplug(struct class_device *class_dev, char **envp,
+firmware_class_uevent(struct class_device *class_dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
@@ -104,13 +104,12 @@
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
return -ENODEV;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "FIRMWARE=%s", fw_priv->fw_id))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "FIRMWARE=%s", fw_priv->fw_id))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "TIMEOUT=%i", loading_timeout))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "TIMEOUT=%i", loading_timeout))
return -ENOMEM;
-
envp[i] = NULL;
return 0;
@@ -352,7 +351,7 @@
static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
- const char *fw_name, struct device *device, int hotplug)
+ const char *fw_name, struct device *device, int uevent)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -384,7 +383,7 @@
goto error_unreg;
}
- if (hotplug)
+ if (uevent)
set_bit(FW_STATUS_READY, &fw_priv->status);
else
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
@@ -399,7 +398,7 @@
static int
_request_firmware(const struct firmware **firmware_p, const char *name,
- struct device *device, int hotplug)
+ struct device *device, int uevent)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -418,19 +417,19 @@
}
retval = fw_setup_class_device(firmware, &class_dev, name, device,
- hotplug);
+ uevent);
if (retval)
goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev);
- if (hotplug) {
+ if (uevent) {
if (loading_timeout > 0) {
fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
add_timer(&fw_priv->timeout);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&class_dev->kobj, KOBJ_ADD);
wait_for_completion(&fw_priv->completion);
set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout);
@@ -456,7 +455,7 @@
}
/**
- * request_firmware: - request firmware to hotplug and wait for it
+ * request_firmware: - send firmware request and wait for it
* @firmware_p: pointer to firmware image
* @name: name of firmware file
* @device: device for which firmware is being loaded
@@ -466,7 +465,7 @@
*
* Should be called from user context where sleeping is allowed.
*
- * @name will be used as $FIRMWARE in the hotplug environment and
+ * @name will be used as $FIRMWARE in the uevent environment and
* should be distinctive enough not to be confused with any other
* firmware image for this or any other device.
**/
@@ -474,8 +473,8 @@
request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device)
{
- int hotplug = 1;
- return _request_firmware(firmware_p, name, device, hotplug);
+ int uevent = 1;
+ return _request_firmware(firmware_p, name, device, uevent);
}
/**
@@ -518,7 +517,7 @@
struct device *device;
void *context;
void (*cont)(const struct firmware *fw, void *context);
- int hotplug;
+ int uevent;
};
static int
@@ -533,7 +532,7 @@
}
daemonize("%s/%s", "firmware", fw_work->name);
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
- fw_work->hotplug);
+ fw_work->uevent);
if (ret < 0)
fw_work->cont(NULL, fw_work->context);
else {
@@ -548,7 +547,7 @@
/**
* request_firmware_nowait: asynchronous version of request_firmware
* @module: module requesting the firmware
- * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ * @uevent: sends uevent to copy the firmware image if this flag
* is non-zero else the firmware copy must be done manually.
* @name: name of firmware file
* @device: device for which firmware is being loaded
@@ -562,7 +561,7 @@
**/
int
request_firmware_nowait(
- struct module *module, int hotplug,
+ struct module *module, int uevent,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
@@ -583,7 +582,7 @@
.device = device,
.context = context,
.cont = cont,
- .hotplug = hotplug,
+ .uevent = uevent,
};
ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index bc3ca6a..7e1d077 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -29,12 +29,12 @@
set_kset_name(MEMORY_CLASS_NAME),
};
-static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
{
return MEMORY_CLASS_NAME;
}
-static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
int retval = 0;
@@ -42,9 +42,9 @@
return retval;
}
-static struct kset_hotplug_ops memory_hotplug_ops = {
- .name = memory_hotplug_name,
- .hotplug = memory_hotplug,
+static struct kset_uevent_ops memory_uevent_ops = {
+ .name = memory_uevent_name,
+ .uevent = memory_uevent,
};
static struct notifier_block *memory_chain;
@@ -431,7 +431,7 @@
unsigned int i;
int ret;
- memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
+ memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
ret = sysdev_class_register(&memory_sysdev_class);
/*
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 8827daf..0f81731 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -25,6 +25,7 @@
struct device platform_bus = {
.bus_id = "platform",
};
+EXPORT_SYMBOL_GPL(platform_bus);
/**
* platform_get_resource - get a resource for a device
@@ -49,6 +50,7 @@
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource);
/**
* platform_get_irq - get an IRQ for a device
@@ -61,6 +63,7 @@
return r ? r->start : 0;
}
+EXPORT_SYMBOL_GPL(platform_get_irq);
/**
* platform_get_resource_byname - get a resource for a device by name
@@ -84,6 +87,7 @@
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
/**
* platform_get_irq - get an IRQ for a device
@@ -96,6 +100,7 @@
return r ? r->start : 0;
}
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
/**
* platform_add_devices - add a numbers of platform devices
@@ -117,6 +122,7 @@
return ret;
}
+EXPORT_SYMBOL_GPL(platform_add_devices);
struct platform_object {
struct platform_device pdev;
@@ -168,7 +174,7 @@
pa->pdev.dev.release = platform_device_release;
}
- return pa ? &pa->pdev : NULL;
+ return pa ? &pa->pdev : NULL;
}
EXPORT_SYMBOL_GPL(platform_device_alloc);
@@ -257,7 +263,7 @@
p = &ioport_resource;
}
- if (p && request_resource(p, r)) {
+ if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d\n",
pdev->dev.bus_id, i);
@@ -282,24 +288,13 @@
EXPORT_SYMBOL_GPL(platform_device_add);
/**
- * platform_device_register - add a platform-level device
- * @pdev: platform device we're adding
- *
- */
-int platform_device_register(struct platform_device * pdev)
-{
- device_initialize(&pdev->dev);
- return platform_device_add(pdev);
-}
-
-/**
- * platform_device_unregister - remove a platform-level device
+ * platform_device_del - remove a platform-level device
* @pdev: platform device we're removing
*
* Note that this function will also release all memory- and port-based
* resources owned by the device (@dev->resource).
*/
-void platform_device_unregister(struct platform_device * pdev)
+void platform_device_del(struct platform_device *pdev)
{
int i;
@@ -310,9 +305,37 @@
release_resource(r);
}
- device_unregister(&pdev->dev);
+ device_del(&pdev->dev);
}
}
+EXPORT_SYMBOL_GPL(platform_device_del);
+
+/**
+ * platform_device_register - add a platform-level device
+ * @pdev: platform device we're adding
+ *
+ */
+int platform_device_register(struct platform_device * pdev)
+{
+ device_initialize(&pdev->dev);
+ return platform_device_add(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_register);
+
+/**
+ * platform_device_unregister - unregister a platform-level device
+ * @pdev: platform device we're unregistering
+ *
+ * Unregistration is done in 2 steps. Fisrt we release all resources
+ * and remove it from the sybsystem, then we drop reference count by
+ * calling platform_device_put().
+ */
+void platform_device_unregister(struct platform_device * pdev)
+{
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_unregister);
/**
* platform_device_register_simple
@@ -355,6 +378,7 @@
platform_device_put(pdev);
return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(platform_device_register_simple);
static int platform_drv_probe(struct device *_dev)
{
@@ -476,6 +500,7 @@
.suspend = platform_suspend,
.resume = platform_resume,
};
+EXPORT_SYMBOL_GPL(platform_bus_type);
int __init platform_bus_init(void)
{
@@ -504,14 +529,3 @@
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif
-
-EXPORT_SYMBOL_GPL(platform_bus);
-EXPORT_SYMBOL_GPL(platform_bus_type);
-EXPORT_SYMBOL_GPL(platform_add_devices);
-EXPORT_SYMBOL_GPL(platform_device_register);
-EXPORT_SYMBOL_GPL(platform_device_register_simple);
-EXPORT_SYMBOL_GPL(platform_device_unregister);
-EXPORT_SYMBOL_GPL(platform_get_irq);
-EXPORT_SYMBOL_GPL(platform_get_resource);
-EXPORT_SYMBOL_GPL(platform_get_irq_byname);
-EXPORT_SYMBOL_GPL(platform_get_resource_byname);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index adbc314..4bafef8 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -64,6 +64,7 @@
}
+#if 0
/**
* dpm_set_power_state - Update power_state field.
* @dev: Device.
@@ -80,3 +81,4 @@
dev->power.power_state = state;
up(&dpm_sem);
}
+#endif /* 0 */
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b4d7a3e..70aeb3a 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -3509,6 +3509,7 @@
return driver_register(&ide_cdrom_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-cdrom*");
module_init(ide_cdrom_init);
module_exit(ide_cdrom_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 449522f..4e57679 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1271,6 +1271,7 @@
return driver_register(&idedisk_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-disk*");
module_init(idedisk_init);
module_exit(idedisk_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 9e293c8..fba3fff 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2197,6 +2197,7 @@
return driver_register(&idefloppy_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-floppy*");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 7d7944e..fab9b2b 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4947,6 +4947,7 @@
return error;
}
+MODULE_ALIAS("ide:*m-tape*");
module_init(idetape_init);
module_exit(idetape_exit);
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8af179b..4b524f6 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1904,9 +1904,69 @@
return 1;
}
+static char *media_string(ide_drive_t *drive)
+{
+ switch (drive->media) {
+ case ide_disk:
+ return "disk";
+ case ide_cdrom:
+ return "cdrom";
+ case ide_tape:
+ return "tape";
+ case ide_floppy:
+ return "floppy";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", media_string(drive));
+}
+
+static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->name);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "ide:m-%s\n", media_string(drive));
+}
+
+static struct device_attribute ide_dev_attrs[] = {
+ __ATTR_RO(media),
+ __ATTR_RO(drivename),
+ __ATTR_RO(modalias),
+ __ATTR_NULL
+};
+
+static int ide_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ int i = 0;
+ int length = 0;
+
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MEDIA=%s", media_string(drive));
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "DRIVENAME=%s", drive->name);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MODALIAS=ide:m-%s", media_string(drive));
+ envp[i] = NULL;
+ return 0;
+}
+
struct bus_type ide_bus_type = {
.name = "ide",
.match = ide_bus_match,
+ .uevent = ide_uevent,
+ .dev_attrs = ide_dev_attrs,
.suspend = generic_ide_suspend,
.resume = generic_ide_resume,
};
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 0ea37b1..f245366 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -121,8 +121,8 @@
};
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size);
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
static struct node_entry *find_entry_by_guid(u64 guid);
@@ -162,7 +162,7 @@
static struct class nodemgr_ud_class = {
.name = "ieee1394",
.release = ud_cls_release,
- .hotplug = nodemgr_hotplug,
+ .uevent = nodemgr_uevent,
};
static struct hpsb_highlevel nodemgr_highlevel;
@@ -966,7 +966,7 @@
if (ud_child == NULL)
break;
- /* inherit unspecified values so hotplug picks it up */
+ /* inherit unspecified values, the driver core picks it up */
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
!(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
{
@@ -1062,8 +1062,8 @@
#ifdef CONFIG_HOTPLUG
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct unit_directory *ud;
int i = 0;
@@ -1112,8 +1112,8 @@
#else
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -1618,8 +1618,8 @@
/* Scan our nodes to get the bus options and create node
* entries. This does not do the sysfs stuff, since that
- * would trigger hotplug callbacks and such, which is a
- * bad idea at this point. */
+ * would trigger uevents and such, which is a bad idea at
+ * this point. */
nodemgr_node_scan(hi, generation);
/* This actually does the full probe, with sysfs
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 08648b1a..1f1743c 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -434,24 +434,24 @@
kfree(dev);
}
-static int ib_device_hotplug(struct class_device *cdev, char **envp,
- int num_envp, char *buf, int size)
+static int ib_device_uevent(struct class_device *cdev, char **envp,
+ int num_envp, char *buf, int size)
{
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
int i = 0, len = 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buf, size, &len,
- "NAME=%s", dev->name))
+ if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
+ "NAME=%s", dev->name))
return -ENOMEM;
/*
- * It might be nice to pass the node GUID to hotplug, but
+ * It might be nice to pass the node GUID with the event, but
* right now the only way to get it is to query the device
* provider, and this can crash during device removal because
* we are will be running after driver removal has started.
* We could add a node_guid field to struct ib_device, or we
- * could just let the hotplug script read the node GUID from
- * sysfs when devices are added.
+ * could just let userspace read the node GUID from sysfs when
+ * devices are added.
*/
envp[i] = NULL;
@@ -653,7 +653,7 @@
static struct class ib_class = {
.name = "infiniband",
.release = ib_device_release,
- .hotplug = ib_device_hotplug,
+ .uevent = ib_device_uevent,
};
int ib_device_register_sysfs(struct ib_device *device)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index bdd2a7f..ef5824c 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -18,7 +18,6 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
-#include <linux/kobject_uevent.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
@@ -529,10 +528,49 @@
INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq);
+static int print_modalias_bits(char *buf, char prefix, unsigned long *arr,
+ unsigned int min, unsigned int max)
+{
+ int len, i;
+
+ len = sprintf(buf, "%c", prefix);
+ for (i = min; i < max; i++)
+ if (arr[LONG(i)] & BIT(i))
+ len += sprintf(buf+len, "%X,", i);
+ return len;
+}
+
+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+{
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len = 0;
+
+ len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-",
+ id->id.bustype,
+ id->id.vendor,
+ id->id.product,
+ id->id.version);
+
+ len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX);
+ len += print_modalias_bits(buf+len, 'k', id->keybit,
+ KEY_MIN_INTERESTING, KEY_MAX);
+ len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX);
+ len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX);
+ len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX);
+ len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX);
+ len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX);
+ len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX);
+ len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX);
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+
static struct attribute *input_dev_attrs[] = {
&class_device_attr_name.attr,
&class_device_attr_phys.attr,
&class_device_attr_uniq.attr,
+ &class_device_attr_modalias.attr,
NULL
};
@@ -611,10 +649,10 @@
}
/*
- * Input hotplugging interface - loading event handlers based on
+ * Input uevent interface - loading event handlers based on
* device bitfields.
*/
-static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *name, unsigned long *bitmap, int max)
{
@@ -639,7 +677,7 @@
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \
- int err = add_hotplug_env_var(envp, num_envp, &i, \
+ int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
@@ -648,15 +686,15 @@
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
do { \
- int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
+ int err = input_add_uevent_bm_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
name, bm, max); \
if (err) \
return err; \
} while (0)
-static int input_dev_hotplug(struct class_device *cdev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int input_dev_uevent(struct class_device *cdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct input_dev *dev = to_input_dev(cdev);
int i = 0;
@@ -698,7 +736,7 @@
struct class input_class = {
.name = "input",
.release = input_dev_release,
- .hotplug = input_dev_hotplug,
+ .uevent = input_dev_uevent,
};
struct input_dev *input_allocate_device(void)
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index fbb69ef..8e530cc 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -800,16 +800,16 @@
#ifdef CONFIG_HOTPLUG
-#define SERIO_ADD_HOTPLUG_VAR(fmt, val...) \
+#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
do { \
- int err = add_hotplug_env_var(envp, num_envp, &i, \
+ int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
struct serio *serio;
int i = 0;
@@ -820,21 +820,21 @@
serio = to_serio_port(dev);
- SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type);
- SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto);
- SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id);
- SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra);
- SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
+ SERIO_ADD_UEVENT_VAR("SERIO_TYPE=%02x", serio->id.type);
+ SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
+ SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
+ SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+ SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
envp[i] = NULL;
return 0;
}
-#undef SERIO_ADD_HOTPLUG_VAR
+#undef SERIO_ADD_UEVENT_VAR
#else
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -908,7 +908,7 @@
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
serio_bus.match = serio_bus_match;
- serio_bus.hotplug = serio_hotplug;
+ serio_bus.uevent = serio_uevent;
serio_bus.resume = serio_resume;
bus_register(&serio_bus);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index c34c96d..228e185 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -128,7 +128,7 @@
return 0;
}
-static int macio_hotplug (struct device *dev, char **envp, int num_envp,
+static int macio_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct macio_dev * macio_dev;
@@ -203,7 +203,7 @@
struct bus_type macio_bus_type = {
.name = "macio",
.match = macio_bus_match,
- .hotplug = macio_hotplug,
+ .uevent = macio_uevent,
.suspend = macio_device_suspend,
.resume = macio_device_resume,
.dev_attrs = macio_dev_attrs,
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 3f4a66c..ec70166 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -80,7 +80,7 @@
}
static int
-mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
int buf_size)
{
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -140,7 +140,7 @@
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
.match = mmc_bus_match,
- .hotplug = mmc_bus_hotplug,
+ .uevent = mmc_bus_uevent,
.suspend = mmc_bus_suspend,
.resume = mmc_bus_resume,
};
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index e1743be..1c97e7d 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -3,8 +3,8 @@
#include <linux/module.h>
#include "pci.h"
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct pci_dev *pdev;
int i = 0;
@@ -17,34 +17,34 @@
if (!pdev)
return -ENODEV;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_CLASS=%04X", pdev->class))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_CLASS=%04X", pdev->class))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+ pdev->subsystem_device))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_SLOT_NAME=%s", pci_name(pdev)))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device,
- (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
- (u8)(pdev->class)))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class)))
return -ENOMEM;
envp[i] = NULL;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a9046d4..7146b69 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -502,8 +502,8 @@
}
#ifndef CONFIG_HOTPLUG
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -512,7 +512,7 @@
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
- .hotplug = pci_hotplug,
+ .uevent = pci_uevent,
.suspend = pci_device_suspend,
.resume = pci_device_resume,
.dev_attrs = pci_dev_attrs,
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6527b36..294849d 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,7 +1,7 @@
/* Functions internal to the PCI core code */
-extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size);
+extern int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index a30aa74..7cf0908 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -901,14 +901,14 @@
EXPORT_SYMBOL(pcmcia_insert_card);
-static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
int i = 0, length = 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "SOCKET_NO=%u", s->sock))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "SOCKET_NO=%u", s->sock))
return -ENOMEM;
envp[i] = NULL;
@@ -927,7 +927,7 @@
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
- .hotplug = pcmcia_socket_hotplug,
+ .uevent = pcmcia_socket_uevent,
.release = pcmcia_release_socket,
.class_release = pcmcia_release_socket_class,
};
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7f8219f..6fb7639 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -779,8 +779,8 @@
#ifdef CONFIG_HOTPLUG
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct pcmcia_device *p_dev;
int i, length = 0;
@@ -800,31 +800,31 @@
i = 0;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "SOCKET_NO=%u",
- p_dev->socket->sock))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "SOCKET_NO=%u",
+ p_dev->socket->sock))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "DEVICE_NO=%02X",
- p_dev->device_no))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEVICE_NO=%02X",
+ p_dev->device_no))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
- "pa%08Xpb%08Xpc%08Xpd%08X",
- p_dev->has_manf_id ? p_dev->manf_id : 0,
- p_dev->has_card_id ? p_dev->card_id : 0,
- p_dev->has_func_id ? p_dev->func_id : 0,
- p_dev->func,
- p_dev->device_no,
- hash[0],
- hash[1],
- hash[2],
- hash[3]))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
+ "pa%08Xpb%08Xpc%08Xpd%08X",
+ p_dev->has_manf_id ? p_dev->manf_id : 0,
+ p_dev->has_card_id ? p_dev->card_id : 0,
+ p_dev->has_func_id ? p_dev->func_id : 0,
+ p_dev->func,
+ p_dev->device_no,
+ hash[0],
+ hash[1],
+ hash[2],
+ hash[3]))
return -ENOMEM;
envp[i] = NULL;
@@ -834,7 +834,7 @@
#else
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -1223,7 +1223,7 @@
struct bus_type pcmcia_bus_type = {
.name = "pcmcia",
- .hotplug = pcmcia_bus_hotplug,
+ .uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match,
.dev_attrs = pcmcia_dev_attrs,
};
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index f49674f..b154b3f 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -56,7 +56,6 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/slab.h>
-#include <linux/kobject_uevent.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/dmi.h>
@@ -106,8 +105,6 @@
char *argv [3], **envp, *buf, *scratch;
int i = 0, value;
- if (!hotplug_path [0])
- return -ENOENT;
if (!current->fs->root) {
return -EAGAIN;
}
@@ -119,8 +116,9 @@
return -ENOMEM;
}
- /* only one standardized param to hotplug command: type */
- argv [0] = hotplug_path;
+ /* FIXME: if there are actual users of this, it should be integrated into
+ * the driver core and use the usual infrastructure like sysfs and uevents */
+ argv [0] = "/sbin/pnpbios";
argv [1] = "dock";
argv [2] = NULL;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e7bd7f3..be9d2d6 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -45,7 +45,7 @@
return 0;
}
static int
-ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
+ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
int buffer_size)
{
/* TODO */
@@ -55,7 +55,7 @@
static struct bus_type ccwgroup_bus_type = {
.name = "ccwgroup",
.match = ccwgroup_bus_match,
- .hotplug = ccwgroup_hotplug,
+ .uevent = ccwgroup_uevent,
};
static inline void
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 811c9d1..85908ca 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -59,7 +59,7 @@
* Heavily modeled on pci and usb hotplug.
*/
static int
-ccw_hotplug (struct device *dev, char **envp, int num_envp,
+ccw_uevent (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct ccw_device *cdev = to_ccwdev(dev);
@@ -110,7 +110,7 @@
struct bus_type ccw_bus_type = {
.name = "ccw",
.match = &ccw_bus_match,
- .hotplug = &ccw_hotplug,
+ .uevent = &ccw_uevent,
};
static int io_subchannel_probe (struct device *);
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 4010f2b..790fcbb 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -34,7 +34,6 @@
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/kobject_uevent.h>
#include <linux/proc_fs.h>
#include <linux/syscalls.h>
#include "z90crypt.h"
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index b6714da..27acf78 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2132,7 +2132,7 @@
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE, NULL);
+ kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
LEAVE;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 56a3520..13d1d36 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -192,6 +192,7 @@
iface->condition = USB_INTERFACE_UNBOUND;
mark_quiesced(iface);
}
+
struct find_interface_arg {
int minor;
struct usb_interface *interface;
@@ -236,10 +237,7 @@
#ifdef CONFIG_HOTPLUG
/*
- * USB hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when USB devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
+ * This sends an uevent to userspace, 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.
*
@@ -248,8 +246,8 @@
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
* device (and this configuration!) are still present.
*/
-static int usb_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct usb_interface *intf;
struct usb_device *usb_dev;
@@ -261,7 +259,7 @@
return -ENODEV;
/* driver is often null here; dev_dbg() would oops */
- pr_debug ("usb %s: hotplug\n", dev->bus_id);
+ pr_debug ("usb %s: uevent\n", dev->bus_id);
/* Must check driver_data here, as on remove driver is always NULL */
if ((dev->driver == &usb_generic_driver) ||
@@ -288,51 +286,51 @@
*
* FIXME reduce hardwired intelligence here
*/
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "DEVICE=/proc/bus/usb/%03d/%03d",
- usb_dev->bus->busnum, usb_dev->devnum))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEVICE=/proc/bus/usb/%03d/%03d",
+ usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM;
#endif
/* per-device configurations are common */
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PRODUCT=%x/%x/%x",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PRODUCT=%x/%x/%x",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM;
/* class-based driver binding models */
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "TYPE=%d/%d/%d",
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "TYPE=%d/%d/%d",
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "INTERFACE=%d/%d/%d",
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "INTERFACE=%d/%d/%d",
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice),
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol,
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol,
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
return -ENOMEM;
envp[i] = NULL;
@@ -342,7 +340,7 @@
#else
-static int usb_hotplug (struct device *dev, char **envp,
+static int usb_uevent(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
return -ENODEV;
@@ -1093,7 +1091,7 @@
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
- .hotplug = usb_hotplug,
+ .uevent = usb_uevent,
.suspend = usb_generic_suspend,
.resume = usb_generic_resume,
};
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 0eaabeb..641268d 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -4397,7 +4397,7 @@
device_initialize(&fake_device);
kobject_set_name(&fake_device.kobj, "etrax_usb");
kobject_add(&fake_device.kobj);
- kobject_hotplug(&fake_device.kobj, KOBJ_ADD);
+ kobject_uevent(&fake_device.kobj, KOBJ_ADD);
hc->bus->controller = &fake_device;
usb_register_bus(hc->bus);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 14016b1..024206c 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -142,12 +142,12 @@
/* Default family */
static struct w1_family w1_default_family;
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
- .hotplug = w1_hotplug,
+ .uevent = w1_uevent,
};
struct device_driver w1_master_driver = {
@@ -361,7 +361,7 @@
}
#ifdef CONFIG_HOTPLUG
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
struct w1_master *md = NULL;
struct w1_slave *sl = NULL;
@@ -377,7 +377,7 @@
event_owner = "slave";
name = sl->name;
} else {
- dev_dbg(dev, "Unknown hotplug event.\n");
+ dev_dbg(dev, "Unknown event.\n");
return -EINVAL;
}
@@ -386,18 +386,18 @@
if (dev->driver != &w1_slave_driver || !sl)
return 0;
- err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+ err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
if (err)
return err;
- err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+ err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
if (err)
return err;
return 0;
};
#else
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
return 0;
}
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 8dc1822..7881ce0 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -226,7 +226,7 @@
static ssize_t part_uevent_store(struct hd_struct * p,
const char *page, size_t count)
{
- kobject_hotplug(&p->kobj, KOBJ_ADD);
+ kobject_uevent(&p->kobj, KOBJ_ADD);
return count;
}
static ssize_t part_dev_read(struct hd_struct * p, char *page)
@@ -336,12 +336,31 @@
disk->part[part-1] = p;
}
+static char *make_block_name(struct gendisk *disk)
+{
+ char *name;
+ static char *block_str = "block:";
+ int size;
+
+ size = strlen(block_str) + strlen(disk->disk_name) + 1;
+ name = kmalloc(size, GFP_KERNEL);
+ if (!name)
+ return NULL;
+ strcpy(name, block_str);
+ strcat(name, disk->disk_name);
+ return name;
+}
+
static void disk_sysfs_symlinks(struct gendisk *disk)
{
struct device *target = get_device(disk->driverfs_dev);
if (target) {
+ char *disk_name = make_block_name(disk);
sysfs_create_link(&disk->kobj,&target->kobj,"device");
- sysfs_create_link(&target->kobj,&disk->kobj,"block");
+ if (disk_name) {
+ sysfs_create_link(&target->kobj,&disk->kobj,disk_name);
+ kfree(disk_name);
+ }
}
}
@@ -360,7 +379,7 @@
if ((err = kobject_add(&disk->kobj)))
return;
disk_sysfs_symlinks(disk);
- kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
/* No minors to use for partitions */
if (disk->minors == 1) {
@@ -461,10 +480,14 @@
devfs_remove_disk(disk);
if (disk->driverfs_dev) {
+ char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device");
- sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
+ if (disk_name) {
+ sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name);
+ kfree(disk_name);
+ }
put_device(disk->driverfs_dev);
}
- kobject_hotplug(&disk->kobj, KOBJ_REMOVE);
+ kobject_uevent(&disk->kobj, KOBJ_REMOVE);
kobject_del(&disk->kobj);
}
diff --git a/fs/super.c b/fs/super.c
index 6689dde..5a347a4 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -665,16 +665,6 @@
return (void *)s->s_bdev == data;
}
-static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
-{
- if (bdev->bd_disk) {
- if (bdev->bd_part)
- kobject_uevent(&bdev->bd_part->kobj, action, NULL);
- else
- kobject_uevent(&bdev->bd_disk->kobj, action, NULL);
- }
-}
-
struct super_block *get_sb_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int))
@@ -717,10 +707,8 @@
up_write(&s->s_umount);
deactivate_super(s);
s = ERR_PTR(error);
- } else {
+ } else
s->s_flags |= MS_ACTIVE;
- bdev_uevent(bdev, KOBJ_MOUNT);
- }
}
return s;
@@ -736,7 +724,6 @@
{
struct block_device *bdev = sb->s_bdev;
- bdev_uevent(bdev, KOBJ_UMOUNT);
generic_shutdown_super(sb);
sync_blockdev(bdev);
close_bdev_excl(bdev);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 59734ba..d367803 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -112,7 +112,11 @@
}
}
if (error && (error != -EEXIST)) {
- sysfs_put((*d)->d_fsdata);
+ struct sysfs_dirent *sd = (*d)->d_fsdata;
+ if (sd) {
+ list_del_init(&sd->s_sibling);
+ sysfs_put(sd);
+ }
d_drop(*d);
}
dput(*d);
diff --git a/include/linux/device.h b/include/linux/device.h
index 17cbc6d..0cdee78 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -47,8 +47,8 @@
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
- int (*hotplug) (struct device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size);
+ int (*uevent)(struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
@@ -151,7 +151,7 @@
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
- int (*hotplug)(struct class_device *dev, char **envp,
+ int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
void (*release)(struct class_device *dev);
@@ -209,9 +209,9 @@
* set, this will be called instead of the class specific release function.
* Only use this if you want to override the default release function, like
* when you are nesting class_device structures.
- * @hotplug: pointer to a hotplug function for this struct class_device. If
- * set, this will be called instead of the class specific hotplug function.
- * Only use this if you want to override the default hotplug function, like
+ * @uevent: pointer to a uevent function for this struct class_device. If
+ * set, this will be called instead of the class specific uevent function.
+ * Only use this if you want to override the default uevent function, like
* when you are nesting class_device structures.
*/
struct class_device {
@@ -227,7 +227,7 @@
struct class_device *parent; /* parent of this child device, if there is one */
void (*release)(struct class_device *dev);
- int (*hotplug)(struct class_device *dev, char **envp,
+ int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
char class_id[BUS_ID_SIZE]; /* unique to this class */
};
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 2063c08..2d71608 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -14,7 +14,7 @@
int request_firmware(const struct firmware **fw, const char *name,
struct device *device);
int request_firmware_nowait(
- struct module *module, int hotplug,
+ struct module *module, int uevent,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
diff --git a/include/linux/input.h b/include/linux/input.h
index 3c58233..6d4cc3c 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -13,6 +13,7 @@
#include <linux/time.h>
#include <linux/list.h>
#include <linux/device.h>
+#include <linux/mod_devicetable.h>
#else
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -511,6 +512,8 @@
#define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4
+/* We avoid low common keys in module aliases so they don't get huge. */
+#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff
/*
@@ -793,6 +796,44 @@
#define FF_MAX 0x7f
+struct input_device_id {
+
+ kernel_ulong_t flags;
+
+ struct input_id id;
+
+ kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
+
+ kernel_ulong_t driver_info;
+};
+
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
+#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
+
#ifdef __KERNEL__
/*
@@ -901,49 +942,11 @@
};
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
-/*
- * Structure for hotplug & device<->driver matching.
- */
-
-#define INPUT_DEVICE_ID_MATCH_BUS 1
-#define INPUT_DEVICE_ID_MATCH_VENDOR 2
-#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
-#define INPUT_DEVICE_ID_MATCH_VERSION 8
-
-#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
-#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
-#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
-#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
-#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
-#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
-#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
-#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
-#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
-
#define INPUT_DEVICE_ID_MATCH_DEVICE\
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
-struct input_device_id {
-
- unsigned long flags;
-
- struct input_id id;
-
- unsigned long evbit[NBITS(EV_MAX)];
- unsigned long keybit[NBITS(KEY_MAX)];
- unsigned long relbit[NBITS(REL_MAX)];
- unsigned long absbit[NBITS(ABS_MAX)];
- unsigned long mscbit[NBITS(MSC_MAX)];
- unsigned long ledbit[NBITS(LED_MAX)];
- unsigned long sndbit[NBITS(SND_MAX)];
- unsigned long ffbit[NBITS(FF_MAX)];
- unsigned long swbit[NBITS(SW_MAX)];
-
- unsigned long driver_info;
-};
-
struct input_handle;
struct input_handler {
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 7f7403a..2a8d8da 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -23,14 +23,27 @@
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
-#include <linux/kobject_uevent.h>
#include <linux/kernel.h>
#include <asm/atomic.h>
-#define KOBJ_NAME_LEN 20
+#define KOBJ_NAME_LEN 20
+#define UEVENT_HELPER_PATH_LEN 256
-/* counter to tag the hotplug event, read only except for the kobject core */
-extern u64 hotplug_seqnum;
+/* path to the userspace helper executed on an event */
+extern char uevent_helper[];
+
+/* counter to tag the uevent, read only except for the kobject core */
+extern u64 uevent_seqnum;
+
+/* the actions here must match the proper string in lib/kobject_uevent.c */
+typedef int __bitwise kobject_action_t;
+enum kobject_action {
+ KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */
+ KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */
+ KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */
+ KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */
+ KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */
+};
struct kobject {
const char * k_name;
@@ -87,15 +100,14 @@
* of object; multiple ksets can belong to one subsystem. All
* ksets of a subsystem share the subsystem's lock.
*
- * Each kset can support hotplugging; if it does, it will be given
- * the opportunity to filter out specific kobjects from being
- * reported, as well as to add its own "data" elements to the
- * environment being passed to the hotplug helper.
+ * Each kset can support specific event variables; it can
+ * supress the event generation or add subsystem specific
+ * variables carried with the event.
*/
-struct kset_hotplug_ops {
+struct kset_uevent_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);
const char *(*name)(struct kset *kset, struct kobject *kobj);
- int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
+ int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size);
};
@@ -105,7 +117,7 @@
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
- struct kset_hotplug_ops * hotplug_ops;
+ struct kset_uevent_ops * uevent_ops;
};
@@ -153,20 +165,20 @@
struct rw_semaphore rwsem;
};
-#define decl_subsys(_name,_type,_hotplug_ops) \
+#define decl_subsys(_name,_type,_uevent_ops) \
struct subsystem _name##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
- .hotplug_ops =_hotplug_ops, \
+ .uevent_ops =_uevent_ops, \
} \
}
-#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
+#define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
struct subsystem _varname##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
- .hotplug_ops =_hotplug_ops, \
+ .uevent_ops =_uevent_ops, \
} \
}
@@ -241,15 +253,17 @@
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
-#ifdef CONFIG_HOTPLUG
-void kobject_hotplug(struct kobject *kobj, enum kobject_action action);
-int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
+#if defined(CONFIG_HOTPLUG) & defined(CONFIG_NET)
+void kobject_uevent(struct kobject *kobj, enum kobject_action action);
+
+int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
__attribute__((format (printf, 7, 8)));
#else
-static inline void kobject_hotplug(struct kobject *kobj, enum kobject_action action) { }
-static inline int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
+static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
+
+static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
{ return 0; }
diff --git a/include/linux/kobject_uevent.h b/include/linux/kobject_uevent.h
deleted file mode 100644
index aa664fe..0000000
--- a/include/linux/kobject_uevent.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * kobject_uevent.h - list of kobject user events that can be generated
- *
- * Copyright (C) 2004 IBM Corp.
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
- *
- * This file is released under the GPLv2.
- *
- */
-
-#ifndef _KOBJECT_EVENT_H_
-#define _KOBJECT_EVENT_H_
-
-#define HOTPLUG_PATH_LEN 256
-
-/* path to the hotplug userspace helper executed on an event */
-extern char hotplug_path[];
-
-/*
- * If you add an action here, you must also add the proper string to the
- * lib/kobject_uevent.c file.
- */
-typedef int __bitwise kobject_action_t;
-enum kobject_action {
- KOBJ_ADD = (__force kobject_action_t) 0x01, /* add event, for hotplug */
- KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* remove event, for hotplug */
- KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* a sysfs attribute file has changed */
- KOBJ_MOUNT = (__force kobject_action_t) 0x04, /* mount event for block devices */
- KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices */
- KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* offline event for hotplug devices */
- KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* online event for hotplug devices */
-};
-
-
-#ifdef CONFIG_KOBJECT_UEVENT
-int kobject_uevent(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr);
-int kobject_uevent_atomic(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr);
-#else
-static inline int kobject_uevent(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr)
-{
- return 0;
-}
-static inline int kobject_uevent_atomic(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr)
-{
- return 0;
-}
-#endif
-
-#endif
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 17e336f..782090c 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -41,6 +41,7 @@
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
extern int platform_device_add(struct platform_device *pdev);
+extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
struct platform_driver {
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 93fa765..a9b80fc 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -124,7 +124,7 @@
KERN_OVERFLOWUID=46, /* int: overflow UID */
KERN_OVERFLOWGID=47, /* int: overflow GID */
KERN_SHMPATH=48, /* string: path to shm fs */
- KERN_HOTPLUG=49, /* string: path to hotplug policy agent */
+ KERN_HOTPLUG=49, /* string: path to uevent helper (deprecated) */
KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */
KERN_S390_USER_DEBUG_LOGGING=51, /* int: dumps of user faults */
KERN_CORE_USES_PID=52, /* int: use core or core.%pid */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e59d1bd..827cc6d 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -225,7 +225,7 @@
* Device drivers should not attempt to activate configurations. The choice
* of which configuration to install is a policy decision based on such
* considerations as available power, functionality provided, and the user's
- * desires (expressed through hotplug scripts). However, drivers can call
+ * desires (expressed through userspace tools). However, drivers can call
* usb_reset_configuration() to reinitialize the current configuration and
* all its interfaces.
*/
diff --git a/init/Kconfig b/init/Kconfig
index aa29b79..ce737e0 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -197,33 +197,6 @@
can be used independently or with another kernel subsystem,
such as SELinux.
-config HOTPLUG
- bool "Support for hot-pluggable devices" if !ARCH_S390
- default ARCH_S390
- help
- This option is provided for the case where no in-kernel-tree
- modules require HOTPLUG functionality, but a module built
- outside the kernel tree does. Such modules require Y here.
-
-config KOBJECT_UEVENT
- bool "Kernel Userspace Events" if EMBEDDED
- depends on NET
- default y
- help
- This option enables the kernel userspace event layer, which is a
- simple mechanism for kernel-to-user communication over a netlink
- socket.
- The goal of the kernel userspace events layer is to provide a simple
- and efficient events system, that notifies userspace about kobject
- state changes. This will enable applications to just listen for
- events instead of polling system devices and files.
- Hotplug events (kobject addition and removal) are also available on
- the netlink socket in addition to the execution of /sbin/hotplug if
- CONFIG_HOTPLUG is enabled.
-
- Say Y, unless you are building a system requiring minimal memory
- consumption.
-
config IKCONFIG
bool "Kernel .config support"
---help---
@@ -308,6 +281,15 @@
you wait for kallsyms to be fixed.
+config HOTPLUG
+ bool "Support for hot-pluggable devices" if EMBEDDED
+ default y
+ help
+ This option is provided for the case where no hotplug or uevent
+ capabilities is wanted by the kernel. You should only consider
+ disabling this option for embedded systems that do not use modules, a
+ dynamic /dev tree, or dynamic device discovery. Just say Y.
+
config PRINTK
default y
bool "Enable support for printk" if EMBEDDED
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 015fb69..99af8b0 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -15,6 +15,9 @@
#include <linux/module.h>
#include <linux/init.h>
+u64 uevent_seqnum;
+char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
+
#define KERNEL_ATTR_RO(_name) \
static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
@@ -23,11 +26,29 @@
__ATTR(_name, 0644, _name##_show, _name##_store)
#ifdef CONFIG_HOTPLUG
-static ssize_t hotplug_seqnum_show(struct subsystem *subsys, char *page)
+/* current uevent sequence number */
+static ssize_t uevent_seqnum_show(struct subsystem *subsys, char *page)
{
- return sprintf(page, "%llu\n", (unsigned long long)hotplug_seqnum);
+ return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum);
}
-KERNEL_ATTR_RO(hotplug_seqnum);
+KERNEL_ATTR_RO(uevent_seqnum);
+
+/* uevent helper program, used during early boo */
+static ssize_t uevent_helper_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", uevent_helper);
+}
+static ssize_t uevent_helper_store(struct subsystem *subsys, const char *page, size_t count)
+{
+ if (count+1 > UEVENT_HELPER_PATH_LEN)
+ return -ENOENT;
+ memcpy(uevent_helper, page, count);
+ uevent_helper[count] = '\0';
+ if (count && uevent_helper[count-1] == '\n')
+ uevent_helper[count-1] = '\0';
+ return count;
+}
+KERNEL_ATTR_RW(uevent_helper);
#endif
#ifdef CONFIG_KEXEC
@@ -45,7 +66,8 @@
static struct attribute * kernel_attrs[] = {
#ifdef CONFIG_HOTPLUG
- &hotplug_seqnum_attr.attr,
+ &uevent_seqnum_attr.attr,
+ &uevent_helper_attr.attr,
#endif
#ifdef CONFIG_KEXEC
&crash_notes_attr.attr,
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b53115b..345f4a1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -31,6 +31,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/kobject.h>
#include <linux/net.h>
#include <linux/sysrq.h>
#include <linux/highuid.h>
@@ -83,9 +84,6 @@
#ifdef CONFIG_KMOD
extern char modprobe_path[];
#endif
-#ifdef CONFIG_HOTPLUG
-extern char hotplug_path[];
-#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
#endif
@@ -397,8 +395,8 @@
{
.ctl_name = KERN_HOTPLUG,
.procname = "hotplug",
- .data = &hotplug_path,
- .maxlen = HOTPLUG_PATH_LEN,
+ .data = &uevent_helper,
+ .maxlen = UEVENT_HELPER_PATH_LEN,
.mode = 0644,
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
diff --git a/lib/klist.c b/lib/klist.c
index bb2f355..9c94f0b 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -199,6 +199,8 @@
i->i_klist = k;
i->i_head = &k->k_list;
i->i_cur = n;
+ if (n)
+ kref_get(&n->n_ref);
}
EXPORT_SYMBOL_GPL(klist_iter_init_node);
diff --git a/lib/kobject.c b/lib/kobject.c
index a181abe..7a0e680 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -207,7 +207,7 @@
kobject_name(kobj),error);
dump_stack();
} else
- kobject_hotplug(kobj, KOBJ_ADD);
+ kobject_uevent(kobj, KOBJ_ADD);
} else
error = -EINVAL;
return error;
@@ -312,7 +312,7 @@
void kobject_unregister(struct kobject * kobj)
{
pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
- kobject_hotplug(kobj, KOBJ_REMOVE);
+ kobject_uevent(kobj, KOBJ_REMOVE);
kobject_del(kobj);
kobject_put(kobj);
}
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 3ab3754..f56e27a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -19,14 +19,16 @@
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/string.h>
-#include <linux/kobject_uevent.h>
#include <linux/kobject.h>
#include <net/sock.h>
-#define BUFFER_SIZE 1024 /* buffer for the hotplug env */
+#define BUFFER_SIZE 1024 /* buffer for the variables */
#define NUM_ENVP 32 /* number of env pointers */
-#if defined(CONFIG_KOBJECT_UEVENT) || defined(CONFIG_HOTPLUG)
+#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+static DEFINE_SPINLOCK(sequence_lock);
+static struct sock *uevent_sock;
+
static char *action_to_string(enum kobject_action action)
{
switch (action) {
@@ -36,10 +38,6 @@
return "remove";
case KOBJ_CHANGE:
return "change";
- case KOBJ_MOUNT:
- return "mount";
- case KOBJ_UMOUNT:
- return "umount";
case KOBJ_OFFLINE:
return "offline";
case KOBJ_ONLINE:
@@ -48,306 +46,183 @@
return NULL;
}
}
-#endif
-
-#ifdef CONFIG_KOBJECT_UEVENT
-static struct sock *uevent_sock;
/**
- * send_uevent - notify userspace by sending event through netlink socket
+ * kobject_uevent - notify userspace by ending an uevent
*
- * @signal: signal name
- * @obj: object path (kobject)
- * @envp: possible hotplug environment to pass with the message
- * @gfp_mask:
- */
-static int send_uevent(const char *signal, const char *obj,
- char **envp, gfp_t gfp_mask)
-{
- struct sk_buff *skb;
- char *pos;
- int len;
-
- if (!uevent_sock)
- return -EIO;
-
- len = strlen(signal) + 1;
- len += strlen(obj) + 1;
-
- /* allocate buffer with the maximum possible message size */
- skb = alloc_skb(len + BUFFER_SIZE, gfp_mask);
- if (!skb)
- return -ENOMEM;
-
- pos = skb_put(skb, len);
- sprintf(pos, "%s@%s", signal, obj);
-
- /* copy the environment key by key to our continuous buffer */
- if (envp) {
- int i;
-
- for (i = 2; envp[i]; i++) {
- len = strlen(envp[i]) + 1;
- pos = skb_put(skb, len);
- strcpy(pos, envp[i]);
- }
- }
-
- NETLINK_CB(skb).dst_group = 1;
- return netlink_broadcast(uevent_sock, skb, 0, 1, gfp_mask);
-}
-
-static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr, gfp_t gfp_mask)
-{
- char *path;
- char *attrpath;
- char *signal;
- int len;
- int rc = -ENOMEM;
-
- path = kobject_get_path(kobj, gfp_mask);
- if (!path)
- return -ENOMEM;
-
- signal = action_to_string(action);
- if (!signal)
- return -EINVAL;
-
- if (attr) {
- len = strlen(path);
- len += strlen(attr->name) + 2;
- attrpath = kmalloc(len, gfp_mask);
- if (!attrpath)
- goto exit;
- sprintf(attrpath, "%s/%s", path, attr->name);
- rc = send_uevent(signal, attrpath, NULL, gfp_mask);
- kfree(attrpath);
- } else
- rc = send_uevent(signal, path, NULL, gfp_mask);
-
-exit:
- kfree(path);
- return rc;
-}
-
-/**
- * kobject_uevent - notify userspace by sending event through netlink socket
- *
- * @signal: signal name
- * @kobj: struct kobject that the event is happening to
- * @attr: optional struct attribute the event belongs to
- */
-int kobject_uevent(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr)
-{
- return do_kobject_uevent(kobj, action, attr, GFP_KERNEL);
-}
-EXPORT_SYMBOL_GPL(kobject_uevent);
-
-int kobject_uevent_atomic(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr)
-{
- return do_kobject_uevent(kobj, action, attr, GFP_ATOMIC);
-}
-EXPORT_SYMBOL_GPL(kobject_uevent_atomic);
-
-static int __init kobject_uevent_init(void)
-{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
- THIS_MODULE);
-
- if (!uevent_sock) {
- printk(KERN_ERR
- "kobject_uevent: unable to create netlink socket!\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-postcore_initcall(kobject_uevent_init);
-
-#else
-static inline int send_uevent(const char *signal, const char *obj,
- char **envp, int gfp_mask)
-{
- return 0;
-}
-
-#endif /* CONFIG_KOBJECT_UEVENT */
-
-
-#ifdef CONFIG_HOTPLUG
-char hotplug_path[HOTPLUG_PATH_LEN] = "/sbin/hotplug";
-u64 hotplug_seqnum;
-static DEFINE_SPINLOCK(sequence_lock);
-
-/**
- * kobject_hotplug - notify userspace by executing /sbin/hotplug
- *
- * @action: action that is happening (usually "ADD" or "REMOVE")
+ * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
* @kobj: struct kobject that the action is happening to
*/
-void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
+void kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
- char *argv [3];
- char **envp = NULL;
- char *buffer = NULL;
- char *seq_buff;
+ char **envp;
+ char *buffer;
char *scratch;
+ const char *action_string;
+ const char *devpath = NULL;
+ const char *subsystem;
+ struct kobject *top_kobj;
+ struct kset *kset;
+ struct kset_uevent_ops *uevent_ops;
+ u64 seq;
+ char *seq_buff;
int i = 0;
int retval;
- char *kobj_path = NULL;
- const char *name = NULL;
- char *action_string;
- u64 seq;
- struct kobject *top_kobj = kobj;
- struct kset *kset;
- static struct kset_hotplug_ops null_hotplug_ops;
- struct kset_hotplug_ops *hotplug_ops = &null_hotplug_ops;
- /* If this kobj does not belong to a kset,
- try to find a parent that does. */
- if (!top_kobj->kset && top_kobj->parent) {
- do {
- top_kobj = top_kobj->parent;
- } while (!top_kobj->kset && top_kobj->parent);
- }
-
- if (top_kobj->kset)
- kset = top_kobj->kset;
- else
- return;
-
- if (kset->hotplug_ops)
- hotplug_ops = kset->hotplug_ops;
-
- /* If the kset has a filter operation, call it.
- Skip the event, if the filter returns zero. */
- if (hotplug_ops->filter) {
- if (!hotplug_ops->filter(kset, kobj))
- return;
- }
-
- pr_debug ("%s\n", __FUNCTION__);
+ pr_debug("%s\n", __FUNCTION__);
action_string = action_to_string(action);
if (!action_string)
return;
- envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
+ /* search the kset we belong to */
+ top_kobj = kobj;
+ if (!top_kobj->kset && top_kobj->parent) {
+ do {
+ top_kobj = top_kobj->parent;
+ } while (!top_kobj->kset && top_kobj->parent);
+ }
+ if (!top_kobj->kset)
+ return;
+
+ kset = top_kobj->kset;
+ uevent_ops = kset->uevent_ops;
+
+ /* skip the event, if the filter returns zero. */
+ if (uevent_ops && uevent_ops->filter)
+ if (!uevent_ops->filter(kset, kobj))
+ return;
+
+ /* environment index */
+ envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp)
return;
- memset (envp, 0x00, NUM_ENVP * sizeof (char *));
+ /* environment values */
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!buffer)
goto exit;
- if (hotplug_ops->name)
- name = hotplug_ops->name(kset, kobj);
- if (name == NULL)
- name = kobject_name(&kset->kobj);
-
- argv [0] = hotplug_path;
- argv [1] = (char *)name; /* won't be changed but 'const' has to go */
- argv [2] = NULL;
-
- /* minimal command environment */
- envp [i++] = "HOME=/";
- envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
- scratch = buffer;
-
- envp [i++] = scratch;
- scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
-
- kobj_path = kobject_get_path(kobj, GFP_KERNEL);
- if (!kobj_path)
+ /* complete object path */
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath)
goto exit;
- envp [i++] = scratch;
- scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
+ /* originating subsystem */
+ if (uevent_ops && uevent_ops->name)
+ subsystem = uevent_ops->name(kset, kobj);
+ else
+ subsystem = kobject_name(&kset->kobj);
- envp [i++] = scratch;
- scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
+ /* event environemnt for helper process only */
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
- /* reserve space for the sequence,
- * put the real one in after the hotplug call */
+ /* default keys */
+ scratch = buffer;
+ envp [i++] = scratch;
+ scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
+ envp [i++] = scratch;
+ scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
+ envp [i++] = scratch;
+ scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
+
+ /* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
- if (hotplug_ops->hotplug) {
- /* have the kset specific function add its stuff */
- retval = hotplug_ops->hotplug (kset, kobj,
+ /* let the kset specific function add its stuff */
+ if (uevent_ops && uevent_ops->uevent) {
+ retval = uevent_ops->uevent(kset, kobj,
&envp[i], NUM_ENVP - i, scratch,
BUFFER_SIZE - (scratch - buffer));
if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
+ pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval);
goto exit;
}
}
+ /* we will send an event, request a new sequence number */
spin_lock(&sequence_lock);
- seq = ++hotplug_seqnum;
+ seq = ++uevent_seqnum;
spin_unlock(&sequence_lock);
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
- pr_debug ("%s: %s %s seq=%llu %s %s %s %s %s\n",
- __FUNCTION__, argv[0], argv[1], (unsigned long long)seq,
- envp[0], envp[1], envp[2], envp[3], envp[4]);
+ /* send netlink message */
+ if (uevent_sock) {
+ struct sk_buff *skb;
+ size_t len;
- send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
+ /* allocate message with the maximum possible size */
+ len = strlen(action_string) + strlen(devpath) + 2;
+ skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL);
+ if (skb) {
+ /* add header */
+ scratch = skb_put(skb, len);
+ sprintf(scratch, "%s@%s", action_string, devpath);
- if (!hotplug_path[0])
- goto exit;
+ /* copy keys to our continuous event payload buffer */
+ for (i = 2; envp[i]; i++) {
+ len = strlen(envp[i]) + 1;
+ scratch = skb_put(skb, len);
+ strcpy(scratch, envp[i]);
+ }
- retval = call_usermodehelper (argv[0], argv, envp, 0);
- if (retval)
- pr_debug ("%s - call_usermodehelper returned %d\n",
- __FUNCTION__, retval);
+ NETLINK_CB(skb).dst_group = 1;
+ netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
+ }
+ }
+
+ /* call uevent_helper, usually only enabled during early boot */
+ if (uevent_helper[0]) {
+ char *argv [3];
+
+ argv [0] = uevent_helper;
+ argv [1] = (char *)subsystem;
+ argv [2] = NULL;
+ call_usermodehelper (argv[0], argv, envp, 0);
+ }
exit:
- kfree(kobj_path);
+ kfree(devpath);
kfree(buffer);
kfree(envp);
return;
}
-EXPORT_SYMBOL(kobject_hotplug);
+EXPORT_SYMBOL_GPL(kobject_uevent);
/**
- * add_hotplug_env_var - helper for creating hotplug environment variables
+ * add_uevent_var - helper for creating event variables
* @envp: Pointer to table of environment variables, as passed into
- * hotplug() method.
+ * uevent() method.
* @num_envp: Number of environment variable slots available, as
- * passed into hotplug() method.
+ * passed into uevent() method.
* @cur_index: Pointer to current index into @envp. It should be
- * initialized to 0 before the first call to add_hotplug_env_var(),
+ * initialized to 0 before the first call to add_uevent_var(),
* and will be incremented on success.
* @buffer: Pointer to buffer for environment variables, as passed
- * into hotplug() method.
- * @buffer_size: Length of @buffer, as passed into hotplug() method.
+ * into uevent() method.
+ * @buffer_size: Length of @buffer, as passed into uevent() method.
* @cur_len: Pointer to current length of space used in @buffer.
* Should be initialized to 0 before the first call to
- * add_hotplug_env_var(), and will be incremented on success.
+ * add_uevent_var(), and will be incremented on success.
* @format: Format for creating environment variable (of the form
* "XXX=%x") for snprintf().
*
* Returns 0 if environment variable was added successfully or -ENOMEM
* if no space was available.
*/
-int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size, int *cur_len,
- const char *format, ...)
+int add_uevent_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ const char *format, ...)
{
va_list args;
/*
* We check against num_envp - 1 to make sure there is at
- * least one slot left after we return, since the hotplug
- * method needs to set the last slot to NULL.
+ * least one slot left after we return, since kobject_uevent()
+ * needs to set the last slot to NULL.
*/
if (*cur_index >= num_envp - 1)
return -ENOMEM;
@@ -366,6 +241,22 @@
(*cur_index)++;
return 0;
}
-EXPORT_SYMBOL(add_hotplug_env_var);
+EXPORT_SYMBOL_GPL(add_uevent_var);
+
+static int __init kobject_uevent_init(void)
+{
+ uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
+ THIS_MODULE);
+
+ if (!uevent_sock) {
+ printk(KERN_ERR
+ "kobject_uevent: unable to create netlink socket!\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+postcore_initcall(kobject_uevent_init);
#endif /* CONFIG_HOTPLUG */
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index bd7568a..0ed3874 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -78,7 +78,7 @@
};
#ifdef CONFIG_HOTPLUG
-static int bt_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
+static int bt_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
{
struct hci_dev *hdev = class_get_devdata(cdev);
int n, i = 0;
@@ -107,7 +107,7 @@
.name = "bluetooth",
.release = bt_release,
#ifdef CONFIG_HOTPLUG
- .hotplug = bt_hotplug,
+ .uevent = bt_uevent,
#endif
};
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index f6a19d5..2ebdc23 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -248,7 +248,7 @@
if (err)
goto out2;
- kobject_hotplug(&p->kobj, KOBJ_ADD);
+ kobject_uevent(&p->kobj, KOBJ_ADD);
return 0;
out2:
kobject_del(&p->kobj);
@@ -260,7 +260,7 @@
{
pr_debug("br_sysfs_removeif\n");
sysfs_remove_link(&p->br->ifobj, p->dev->name);
- kobject_hotplug(&p->kobj, KOBJ_REMOVE);
+ kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
}
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index e2137f3..e1da81d 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -84,16 +84,11 @@
return ret;
}
-/* generate a read-only network device class attribute */
-#define NETDEVICE_ATTR(field, format_string) \
-NETDEVICE_SHOW(field, format_string) \
-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \
-
-NETDEVICE_ATTR(addr_len, fmt_dec);
-NETDEVICE_ATTR(iflink, fmt_dec);
-NETDEVICE_ATTR(ifindex, fmt_dec);
-NETDEVICE_ATTR(features, fmt_long_hex);
-NETDEVICE_ATTR(type, fmt_dec);
+NETDEVICE_SHOW(addr_len, fmt_dec);
+NETDEVICE_SHOW(iflink, fmt_dec);
+NETDEVICE_SHOW(ifindex, fmt_dec);
+NETDEVICE_SHOW(features, fmt_long_hex);
+NETDEVICE_SHOW(type, fmt_dec);
/* use same locking rules as GIFHWADDR ioctl's */
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
@@ -136,10 +131,6 @@
return -EINVAL;
}
-static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
-static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
-static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
-
/* read-write attributes */
NETDEVICE_SHOW(mtu, fmt_dec);
@@ -153,8 +144,6 @@
return netdev_store(dev, buf, len, change_mtu);
}
-static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
-
NETDEVICE_SHOW(flags, fmt_hex);
static int change_flags(struct net_device *net, unsigned long new_flags)
@@ -167,8 +156,6 @@
return netdev_store(dev, buf, len, change_flags);
}
-static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
-
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
@@ -182,9 +169,6 @@
return netdev_store(dev, buf, len, change_tx_queue_len);
}
-static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
- store_tx_queue_len);
-
NETDEVICE_SHOW(weight, fmt_dec);
static int change_weight(struct net_device *net, unsigned long new_weight)
@@ -198,24 +182,21 @@
return netdev_store(dev, buf, len, change_weight);
}
-static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight,
- store_weight);
-
-
-static struct class_device_attribute *net_class_attributes[] = {
- &class_device_attr_ifindex,
- &class_device_attr_iflink,
- &class_device_attr_addr_len,
- &class_device_attr_tx_queue_len,
- &class_device_attr_features,
- &class_device_attr_mtu,
- &class_device_attr_flags,
- &class_device_attr_weight,
- &class_device_attr_type,
- &class_device_attr_address,
- &class_device_attr_broadcast,
- &class_device_attr_carrier,
- NULL
+static struct class_device_attribute net_class_attributes[] = {
+ __ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
+ __ATTR(iflink, S_IRUGO, show_iflink, NULL),
+ __ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
+ __ATTR(features, S_IRUGO, show_features, NULL),
+ __ATTR(type, S_IRUGO, show_type, NULL),
+ __ATTR(address, S_IRUGO, show_address, NULL),
+ __ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
+ __ATTR(carrier, S_IRUGO, show_carrier, NULL),
+ __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
+ __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
+ __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
+ store_tx_queue_len),
+ __ATTR(weight, S_IRUGO | S_IWUSR, show_weight, store_weight),
+ {}
};
/* Show a given an attribute in the statistics group */
@@ -369,14 +350,14 @@
#endif
#ifdef CONFIG_HOTPLUG
-static int netdev_hotplug(struct class_device *cd, char **envp,
- int num_envp, char *buf, int size)
+static int netdev_uevent(struct class_device *cd, char **envp,
+ int num_envp, char *buf, int size)
{
struct net_device *dev = to_net_dev(cd);
int i = 0;
int n;
- /* pass interface in env to hotplug. */
+ /* pass interface to uevent. */
envp[i++] = buf;
n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1;
buf += n;
@@ -407,8 +388,9 @@
static struct class net_class = {
.name = "net",
.release = netdev_release,
+ .class_dev_attrs = net_class_attributes,
#ifdef CONFIG_HOTPLUG
- .hotplug = netdev_hotplug,
+ .uevent = netdev_uevent,
#endif
};
@@ -431,8 +413,6 @@
int netdev_register_sysfs(struct net_device *net)
{
struct class_device *class_dev = &(net->class_dev);
- int i;
- struct class_device_attribute *attr;
int ret;
class_dev->class = &net_class;
@@ -442,12 +422,6 @@
if ((ret = class_device_register(class_dev)))
goto out;
- for (i = 0; (attr = net_class_attributes[i]) != NULL; i++) {
- if ((ret = class_device_create_file(class_dev, attr)))
- goto out_unreg;
- }
-
-
if (net->get_stats &&
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
goto out_unreg;
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e3d144a..e0eedff 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -16,8 +16,10 @@
* use either stdint.h or inttypes.h for the rest. */
#if KERNEL_ELFCLASS == ELFCLASS32
typedef Elf32_Addr kernel_ulong_t;
+#define BITS_PER_LONG 32
#else
typedef Elf64_Addr kernel_ulong_t;
+#define BITS_PER_LONG 64
#endif
#ifdef __sun__
#include <inttypes.h>
@@ -35,6 +37,7 @@
* even potentially has different endianness and word sizes, since
* we handle those differences explicitly below */
#include "../../include/linux/mod_devicetable.h"
+#include "../../include/linux/input.h"
#define ADD(str, sep, cond, field) \
do { \
@@ -366,6 +369,61 @@
return 1;
}
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void do_input(char *alias,
+ kernel_ulong_t *arr, unsigned int min, unsigned int max)
+{
+ unsigned int i;
+ for (i = min; i < max; i++) {
+ if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+ sprintf(alias+strlen(alias), "%X,*", i);
+ }
+}
+
+/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
+static int do_input_entry(const char *filename, struct input_device_id *id,
+ char *alias)
+{
+ sprintf(alias, "input:");
+
+ ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
+ ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
+ ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
+ id->id.product);
+ ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
+ id->id.version);
+
+ sprintf(alias + strlen(alias), "-e*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
+ do_input(alias, id->evbit, 0, EV_MAX);
+ sprintf(alias + strlen(alias), "k*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
+ do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+ sprintf(alias + strlen(alias), "r*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
+ do_input(alias, id->relbit, 0, REL_MAX);
+ sprintf(alias + strlen(alias), "a*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
+ do_input(alias, id->absbit, 0, ABS_MAX);
+ sprintf(alias + strlen(alias), "m*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
+ do_input(alias, id->mscbit, 0, MSC_MAX);
+ sprintf(alias + strlen(alias), "l*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
+ do_input(alias, id->ledbit, 0, LED_MAX);
+ sprintf(alias + strlen(alias), "s*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
+ do_input(alias, id->sndbit, 0, SND_MAX);
+ sprintf(alias + strlen(alias), "f*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
+ do_input(alias, id->ffbit, 0, SND_MAX);
+ sprintf(alias + strlen(alias), "w*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
+ do_input(alias, id->swbit, 0, SW_MAX);
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -453,7 +511,9 @@
else if (sym_is(symname, "__mod_i2c_device_table"))
do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
do_i2c_entry, mod);
-
+ else if (sym_is(symname, "__mod_input_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct input_device_id),
+ do_input_entry, mod);
}
/* Now add out buffered information to the generated C source */