Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
Linus Torvalds [Thu, 5 Jan 2006 02:44:12 +0000 (18:44 -0800)]
Trivial manual merge fixup for usb_find_interface clashes.

64 files changed:
Documentation/powerpc/eeh-pci-error-recovery.txt
MAINTAINERS
arch/arm/common/amba.c
arch/ia64/sn/kernel/tiocx.c
arch/powerpc/kernel/vio.c
block/genhd.c
drivers/acpi/container.c
drivers/acpi/processor_core.c
drivers/acpi/scan.c
drivers/base/Kconfig
drivers/base/bus.c
drivers/base/class.c
drivers/base/core.c
drivers/base/cpu.c
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/base/memory.c
drivers/base/platform.c
drivers/base/power/runtime.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
drivers/ide/ide-tape.c
drivers/ide/ide.c
drivers/ieee1394/nodemgr.c
drivers/infiniband/core/sysfs.c
drivers/input/input.c
drivers/input/serio/serio.c
drivers/macintosh/macio_asic.c
drivers/mmc/mmc_sysfs.c
drivers/pci/hotplug.c
drivers/pci/pci-driver.c
drivers/pci/pci.h
drivers/pcmcia/cs.c
drivers/pcmcia/ds.c
drivers/pnp/pnpbios/core.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/device.c
drivers/s390/crypto/z90main.c
drivers/scsi/ipr.c
drivers/usb/core/usb.c
drivers/usb/host/hc_crisv10.c
drivers/w1/w1.c
fs/partitions/check.c
fs/super.c
fs/sysfs/dir.c
include/linux/device.h
include/linux/firmware.h
include/linux/input.h
include/linux/kobject.h
include/linux/kobject_uevent.h [deleted file]
include/linux/platform_device.h
include/linux/sysctl.h
include/linux/usb.h
init/Kconfig
kernel/ksysfs.c
kernel/sysctl.c
lib/klist.c
lib/kobject.c
lib/kobject_uevent.c
net/bluetooth/hci_sysfs.c
net/bridge/br_sysfs_if.c
net/core/net-sysfs.c
scripts/mod/file2alias.c

index e75d747..67a11a3 100644 (file)
@@ -115,7 +115,7 @@ Current PPC64 Linux EEH Implementation
 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 @@ A handler for the EEH notifier_block events is implemented in
 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 @@ rpa_php_unconfig_pci_adapter() {             // in rpaphp_pci.c
     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
index 1e59d39..6246b7f 100644 (file)
@@ -1480,12 +1480,6 @@ W:       http://nfs.sourceforge.net/
 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
index e101311..c95ec9e 100644 (file)
@@ -45,7 +45,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
 }
 
 #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 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
        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 int amba_resume(struct device *dev)
 static struct bus_type amba_bustype = {
        .name           = "amba",
        .match          = amba_match,
-       .hotplug        = amba_hotplug,
+       .uevent         = amba_uevent,
        .suspend        = amba_suspend,
        .resume         = amba_resume,
 };
index 0d8592a..768c21d 100644 (file)
@@ -65,7 +65,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
 
 }
 
-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 @@ static void tiocx_bus_release(struct device *dev)
 struct bus_type tiocx_bus_type = {
        .name = "tiocx",
        .match = tiocx_match,
-       .hotplug = tiocx_hotplug,
+       .uevent = tiocx_uevent,
 };
 
 /**
index 71a6add..13c4149 100644 (file)
@@ -293,6 +293,6 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
 
 struct bus_type vio_bus_type = {
        .name = "vio",
-       .hotplug = vio_hotplug,
+       .uevent = vio_hotplug,
        .match = vio_bus_match,
 };
index f04609d..f1ed83f 100644 (file)
@@ -358,7 +358,7 @@ static struct sysfs_ops disk_sysfs_ops = {
 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 @@ static struct kobj_type ktype_block = {
 
 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 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 
        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 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
        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);
 
 
 /*
index 27ec12c..b69a8ca 100644 (file)
@@ -172,21 +172,21 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
                        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:
index 0c561c5..1278aca 100644 (file)
@@ -748,7 +748,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
                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 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
                }
 
                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 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
                }
 
                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,
index 31218e1..0745d20 100644 (file)
@@ -78,7 +78,7 @@ static struct kobj_type ktype_acpi_ns = {
        .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 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
        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 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
        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 @@ static struct kset acpi_namespace_kset = {
                 },
        .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 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 }
 
 /* --------------------------------------------------------------------------
-               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);
index 934149c..f0eff3d 100644 (file)
@@ -19,11 +19,11 @@ config PREVENT_FIRMWARE_BUILD
          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
index fa601b0..29f6af5 100644 (file)
@@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
 
        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 @@ static ssize_t driver_bind(struct device_driver *drv,
 
        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 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
        }
 }
 
+#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 @@ int bus_add_driver(struct device_driver * drv)
                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 @@ int bus_add_driver(struct device_driver * drv)
 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 @@ void bus_remove_driver(struct device_driver * drv)
 /* 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;
 }
 
index db65fd0..df7fdab 100644 (file)
@@ -178,7 +178,7 @@ static void class_device_create_release(struct class_device *class_dev)
 }
 
 /* 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 @@ static struct kobj_type ktype_class_device = {
        .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 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
        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 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
                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 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
        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 show_dev(struct class_device *class_dev, char *buf)
 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 @@ int class_device_add(struct class_device *class_dev)
                                  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 @@ struct class_device *class_device_create(struct class *cls,
        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 @@ void class_device_del(struct class_device *class_dev)
                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);
index 8615b42..fd80599 100644 (file)
@@ -90,7 +90,7 @@ static struct kobj_type ktype_device = {
 };
 
 
-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 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
        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 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 
        /* 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 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
        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 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
        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 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
  *     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 @@ int device_add(struct device *dev)
        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 @@ int device_add(struct device *dev)
  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 @@ void device_del(struct device * dev)
                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);
index a958447..281d267 100644 (file)
@@ -41,14 +41,14 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
        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;
index 3b419c9..2b90501 100644 (file)
@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
  *     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 @@ static int __device_attach(struct device_driver * drv, void * data)
  *
  *     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 @@ static int __driver_attach(struct device * dev, void * data)
         * 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 @@ void driver_attach(struct device_driver * drv)
  *     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 @@ void driver_detach(struct device_driver * drv)
                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);
        }
 }
index 59dacb6..5b3d5e9 100644 (file)
@@ -85,17 +85,17 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
 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 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp,
        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 @@ error_kfree:
 
 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 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
                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 @@ out:
 
 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 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
        }
 
        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 @@ out:
 }
 
 /**
- * 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 @@ out:
  *
  *      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 @@ int
 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 firmware_work {
        struct device *device;
        void *context;
        void (*cont)(const struct firmware *fw, void *context);
-       int hotplug;
+       int uevent;
 };
 
 static int
@@ -533,7 +532,7 @@ request_firmware_work_func(void *arg)
        }
        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_work_func(void *arg)
 /**
  * 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 @@ request_firmware_work_func(void *arg)
  **/
 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 @@ request_firmware_nowait(
                .device = device,
                .context = context,
                .cont = cont,
-               .hotplug = hotplug,
+               .uevent = uevent,
        };
 
        ret = kernel_thread(request_firmware_work_func, fw_work,
index bc3ca6a..7e1d077 100644 (file)
@@ -29,12 +29,12 @@ static struct sysdev_class memory_sysdev_class = {
        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 @@ static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
        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 @@ int __init memory_dev_init(void)
        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);
 
        /*
index 8827daf..0f81731 100644 (file)
@@ -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 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(platform_get_resource);
 
 /**
  *     platform_get_irq - get an IRQ for a device
@@ -61,6 +63,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
 
        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 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
 
 /**
  *     platform_get_irq - get an IRQ for a device
@@ -96,6 +100,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name)
 
        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 @@ int platform_add_devices(struct platform_device **devs, int num)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(platform_add_devices);
 
 struct platform_object {
        struct platform_device pdev;
@@ -168,7 +174,7 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
                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 @@ int platform_device_add(struct platform_device *pdev)
                                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 @@ int platform_device_add(struct platform_device *pdev)
 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 @@ void platform_device_unregister(struct platform_device * pdev)
                                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 @@ error:
        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 @@ struct bus_type platform_bus_type = {
        .suspend        = platform_suspend,
        .resume         = platform_resume,
 };
+EXPORT_SYMBOL_GPL(platform_bus_type);
 
 int __init platform_bus_init(void)
 {
@@ -504,14 +529,3 @@ u64 dma_get_required_mask(struct device *dev)
 }
 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);
index adbc314..4bafef8 100644 (file)
@@ -64,6 +64,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
 }
 
 
+#if 0
 /**
  *     dpm_set_power_state - Update power_state field.
  *     @dev:   Device.
@@ -80,3 +81,4 @@ void dpm_set_power_state(struct device * dev, pm_message_t state)
        dev->power.power_state = state;
        up(&dpm_sem);
 }
+#endif  /*  0  */
index b4d7a3e..70aeb3a 100644 (file)
@@ -3509,6 +3509,7 @@ static int __init ide_cdrom_init(void)
        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");
index 449522f..4e57679 100644 (file)
@@ -1271,6 +1271,7 @@ static int __init idedisk_init(void)
        return driver_register(&idedisk_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-disk*");
 module_init(idedisk_init);
 module_exit(idedisk_exit);
 MODULE_LICENSE("GPL");
index 9e293c8..fba3fff 100644 (file)
@@ -2197,6 +2197,7 @@ static int __init idefloppy_init(void)
        return driver_register(&idefloppy_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-floppy*");
 module_init(idefloppy_init);
 module_exit(idefloppy_exit);
 MODULE_LICENSE("GPL");
index 7d7944e..fab9b2b 100644 (file)
@@ -4947,6 +4947,7 @@ out:
        return error;
 }
 
+MODULE_ALIAS("ide:*m-tape*");
 module_init(idetape_init);
 module_exit(idetape_exit);
 MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
index 8af179b..4b524f6 100644 (file)
@@ -1904,9 +1904,69 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
        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,
 };
index 0ea37b1..f245366 100644 (file)
@@ -121,8 +121,8 @@ struct host_info {
 };
 
 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 void ud_cls_release(struct class_device *class_dev)
 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 @@ static struct unit_directory *nodemgr_process_unit_directory
                                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 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
 
 #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 @@ do {                                                              \
 
 #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 @@ static int nodemgr_host_thread(void *__hi)
 
                /* 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
index 08648b1..1f1743c 100644 (file)
@@ -434,24 +434,24 @@ static void ib_device_release(struct class_device *cdev)
        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_device_attribute *ib_class_attributes[] = {
 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)
index bdd2a7f..ef5824c 100644 (file)
@@ -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(name);
 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 @@ static void input_dev_release(struct class_device *class_dev)
 }
 
 /*
- * 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 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
 
 #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 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
 
 #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 @@ static int input_dev_hotplug(struct class_device *cdev, char **envp,
 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)
index fbb69ef..8e530cc 100644 (file)
@@ -800,16 +800,16 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
 
 #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 @@ static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *bu
 
        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 @@ static int __init serio_init(void)
        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);
 
index c34c96d..228e185 100644 (file)
@@ -128,7 +128,7 @@ static int macio_device_resume(struct device * dev)
        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 @@ extern struct device_attribute macio_dev_attrs[];
 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,
index 3f4a66c..ec70166 100644 (file)
@@ -80,7 +80,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 }
 
 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 @@ static struct bus_type mmc_bus_type = {
        .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,
 };
index e1743be..1c97e7d 100644 (file)
@@ -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 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
        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;
index a9046d4..7146b69 100644 (file)
@@ -502,8 +502,8 @@ void pci_dev_put(struct pci_dev *dev)
 }
 
 #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 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
 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,
index 6527b36..294849d 100644 (file)
@@ -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);
index a30aa74..7cf0908 100644 (file)
@@ -901,14 +901,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
 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 @@ static void pcmcia_release_socket_class(struct class *data)
 
 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,
 };
index 7f8219f..6fb7639 100644 (file)
@@ -779,8 +779,8 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
 
 #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 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
 
        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 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
 
 #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 @@ static struct class_interface pcmcia_bus_interface = {
 
 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,
 };
index f49674f..b154b3f 100644 (file)
@@ -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 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
        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 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
                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;
 
index e7bd7f3..be9d2d6 100644 (file)
@@ -45,7 +45,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
        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 @@ ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
 static struct bus_type ccwgroup_bus_type = {
        .name    = "ccwgroup",
        .match   = ccwgroup_bus_match,
-       .hotplug = ccwgroup_hotplug,
+       .uevent = ccwgroup_uevent,
 };
 
 static inline void
index 811c9d1..85908ca 100644 (file)
@@ -59,7 +59,7 @@ ccw_bus_match (struct device * dev, struct device_driver * drv)
  * 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 @@ ccw_hotplug (struct device *dev, char **envp, int num_envp,
 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 *);
index 4010f2b..790fcbb 100644 (file)
@@ -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"
index b6714da..27acf78 100644 (file)
@@ -2132,7 +2132,7 @@ restart:
        }
 
        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;
 }
 
index 56a3520..13d1d36 100644 (file)
@@ -192,6 +192,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
        iface->condition = USB_INTERFACE_UNBOUND;
        mark_quiesced(iface);
 }
+
 struct find_interface_arg {
        int minor;
        struct usb_interface *interface;
@@ -236,10 +237,7 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 #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 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
  * 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 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
                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 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
         *
         * 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 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 
 #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 @@ static int usb_generic_resume(struct device *dev)
 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,
 };
index 0eaabeb..641268d 100644 (file)
@@ -4397,7 +4397,7 @@ static int __init etrax_usb_hc_init(void)
         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);
 
index 14016b1..024206c 100644 (file)
@@ -142,12 +142,12 @@ static struct bin_attribute w1_slave_attr_bin_id = {
 /* 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 @@ void w1_destroy_master_attributes(struct w1_master *master)
 }
 
 #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 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
                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 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
        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;
 }
index 8dc1822..7881ce0 100644 (file)
@@ -226,7 +226,7 @@ static struct sysfs_ops part_sysfs_ops = {
 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 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
        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 @@ void register_disk(struct gendisk *disk)
        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 @@ void del_gendisk(struct gendisk *disk)
        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);
 }
index 6689dde..5a347a4 100644 (file)
@@ -665,16 +665,6 @@ static int test_bdev_super(struct super_block *s, void *data)
        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 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
                        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 @@ void kill_block_super(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
 
-       bdev_uevent(bdev, KOBJ_UMOUNT);
        generic_shutdown_super(sb);
        sync_blockdev(bdev);
        close_bdev_excl(bdev);
index 59734ba..d367803 100644 (file)
@@ -112,7 +112,11 @@ static int create_dir(struct kobject * k, struct dentry * p,
                        }
                }
                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);
index 17cbc6d..0cdee78 100644 (file)
@@ -47,8 +47,8 @@ struct bus_type {
        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 {
        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 @@ extern int class_device_create_file(struct class_device *,
  * 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 {
        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 */
 };
index 2063c08..2d71608 100644 (file)
@@ -14,7 +14,7 @@ struct device;
 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));
 
index 3c58233..6d4cc3c 100644 (file)
@@ -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 @@ struct input_absinfo {
 #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 @@ struct ff_effect {
 
 #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 @@ struct input_dev {
 };
 #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 {
index 7f7403a..2a8d8da 100644 (file)
 #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 @@ struct kobj_type {
  *     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 kset {
        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 subsystem {
        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 @@ struct subsys_attribute {
 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 (file)
index aa664fe..0000000
+++ /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
index 17e336f..782090c 100644 (file)
@@ -41,6 +41,7 @@ extern struct platform_device *platform_device_alloc(const char *name, unsigned
 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 {
index 93fa765..a9b80fc 100644 (file)
@@ -124,7 +124,7 @@ enum
        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 */
index e59d1bd..827cc6d 100644 (file)
@@ -225,7 +225,7 @@ struct usb_interface_cache {
  * 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.
  */
index aa29b79..ce737e0 100644 (file)
@@ -197,33 +197,6 @@ config AUDITSYSCALL
          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 @@ config KALLSYMS_EXTRA_PASS
           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
index 015fb69..99af8b0 100644 (file)
@@ -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 @@ static struct subsys_attribute _name##_attr = \
        __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)uevent_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)
 {
-       return sprintf(page, "%llu\n", (unsigned long long)hotplug_seqnum);
+       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_RO(hotplug_seqnum);
+KERNEL_ATTR_RW(uevent_helper);
 #endif
 
 #ifdef CONFIG_KEXEC
@@ -45,7 +66,8 @@ EXPORT_SYMBOL_GPL(kernel_subsys);
 
 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,
index b53115b..345f4a1 100644 (file)
@@ -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 @@ static int ngroups_max = NGROUPS_MAX;
 #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 @@ static ctl_table kern_table[] = {
        {
                .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,
index bb2f355..9c94f0b 100644 (file)
@@ -199,6 +199,8 @@ void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_
        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);
index a181abe..7a0e680 100644 (file)
@@ -207,7 +207,7 @@ int kobject_register(struct kobject * kobj)
                               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_del(struct kobject * kobj)
 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);
 }
index 3ab3754..f56e27a 100644 (file)
 #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 @@ static char *action_to_string(enum kobject_action action)
                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 @@ static char *action_to_string(enum kobject_action action)
                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. */
+       pr_debug("%s\n", __FUNCTION__);
+
+       action_string = action_to_string(action);
+       if (!action_string)
+               return;
+
+       /* 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)
-               kset = top_kobj->kset;
-       else
+       if (!top_kobj->kset)
                return;
 
-       if (kset->hotplug_ops)
-               hotplug_ops = kset->hotplug_ops;
+       kset = top_kobj->kset;
+       uevent_ops = kset->uevent_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))
+       /*  skip the event, if the filter returns zero. */
+       if (uevent_ops && uevent_ops->filter)
+               if (!uevent_ops->filter(kset, kobj))
                        return;
-       }
 
-       pr_debug ("%s\n", __FUNCTION__);
-
-       action_string = action_to_string(action);
-       if (!action_string)
-               return;
-
-       envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
+       /* 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);
+       /* complete object path */
+       devpath = kobject_get_path(kobj, GFP_KERNEL);
+       if (!devpath)
+               goto exit;
 
-       argv [0] = hotplug_path;
-       argv [1] = (char *)name; /* won't be changed but 'const' has to go */
-       argv [2] = NULL;
+       /* originating subsystem */
+       if (uevent_ops && uevent_ops->name)
+               subsystem = uevent_ops->name(kset, kobj);
+       else
+               subsystem = kobject_name(&kset->kobj);
 
-       /* minimal command environment */
-       envp [i++] = "HOME=/";
-       envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+       /* event environemnt for helper process only */
+       envp[i++] = "HOME=/";
+       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 
+       /* default keys */
        scratch = buffer;
-
        envp [i++] = scratch;
        scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
-
-       kobj_path = kobject_get_path(kobj, GFP_KERNEL);
-       if (!kobj_path)
-               goto exit;
-
        envp [i++] = scratch;
-       scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
-
+       scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
        envp [i++] = scratch;
-       scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
+       scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
 
-       /* reserve space for the sequence,
-        * put the real one in after the hotplug call */
+       /* 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_uevent(action_string, kobj_path, envp, GFP_KERNEL);
+       /* send netlink message */
+       if (uevent_sock) {
+               struct sk_buff *skb;
+               size_t len;
+
+               /* 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);
+
+                       /* 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]);
+                       }
+
+                       NETLINK_CB(skb).dst_group = 1;
+                       netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
+               }
+       }
 
-       if (!hotplug_path[0])
-               goto exit;
+       /* call uevent_helper, usually only enabled during early boot */
+       if (uevent_helper[0]) {
+               char *argv [3];
 
-       retval = call_usermodehelper (argv[0], argv, envp, 0);
-       if (retval)
-               pr_debug ("%s - call_usermodehelper returned %d\n",
-                         __FUNCTION__, retval);
+               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 @@ int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
        (*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 */
index bd7568a..0ed3874 100644 (file)
@@ -78,7 +78,7 @@ static struct class_device_attribute *bt_attrs[] = {
 };
 
 #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 @@ struct class bt_class = {
        .name           = "bluetooth",
        .release        = bt_release,
 #ifdef CONFIG_HOTPLUG
-       .hotplug        = bt_hotplug,
+       .uevent         = bt_uevent,
 #endif
 };
 
index f6a19d5..2ebdc23 100644 (file)
@@ -248,7 +248,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
        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 @@ void br_sysfs_removeif(struct net_bridge_port *p)
 {
        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);
 }
 
index e2137f3..e1da81d 100644 (file)
@@ -84,16 +84,11 @@ static ssize_t netdev_store(struct class_device *dev,
        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 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
        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 @@ static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
        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 @@ static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len
        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 @@ static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, siz
        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 @@ static ssize_t store_weight(struct class_device *dev, const char *buf, size_t le
        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 @@ static struct attribute_group wireless_group = {
 #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 void netdev_release(struct class_device *cd)
 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 @@ void netdev_unregister_sysfs(struct net_device * net)
 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 @@ int netdev_register_sysfs(struct net_device *net)
        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; 
index e3d144a..e0eedff 100644 (file)
  * 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 @@ typedef unsigned char __u8;
  * 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 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *a
        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 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
        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 */