From 43cc71eed1250755986da4c0f9898f9a635cb3bf Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 18 Aug 2007 04:40:39 +0200 Subject: platform: prefix MODALIAS with "platform:" Prefix platform modalias strings with "platform:", which modprobe config to blacklist alias resolving if userspace configures it. Send uevents for all platform devices. Add MODULE_ALIAS's to: pxa2xx_pcmcia, ds1742 and pcspkr to trigger module autoloading by userspace. $ modinfo pcspkr alias: platform:pcspkr license: GPL description: PC Speaker beeper driver ... $ modprobe -n -v platform:pcspkr insmod /lib/modules/2.6.23-rc3-g28e8351a-dirty/kernel/drivers/input/misc/pcspkr.ko Signed-off-by: Kay Sievers Cc: David Brownell Cc: Atsushi Nemoto Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 15 ++------------- drivers/input/misc/pcspkr.c | 1 + drivers/pcmcia/pxa2xx_mainstone.c | 2 +- drivers/pcmcia/pxa2xx_sharpsl.c | 2 +- 4 files changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 869ff8c00146..9bfc434d1327 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -160,11 +160,6 @@ static void platform_device_release(struct device *dev) * * Create a platform device object which can have other objects attached * to it, and which will have attached objects freed when it is released. - * - * This device will be marked as not supporting hotpluggable drivers; no - * device add/remove uevents will be generated. In the unusual case that - * the device isn't being dynamically allocated as a legacy "probe the - * hardware" driver, infrastructure code should reverse this marking. */ struct platform_device *platform_device_alloc(const char *name, unsigned int id) { @@ -177,12 +172,6 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id) pa->pdev.id = id; device_initialize(&pa->pdev.dev); pa->pdev.dev.release = platform_device_release; - - /* prevent hotplug "modprobe $(MODALIAS)" from causing trouble in - * legacy probe-the-hardware drivers, which don't properly split - * out device enumeration logic from drivers. - */ - pa->pdev.dev.uevent_suppress = 1; } return pa ? &pa->pdev : NULL; @@ -530,7 +519,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, char *buf) { struct platform_device *pdev = to_platform_device(dev); - int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name); + int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name); return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; } @@ -546,7 +535,7 @@ static int platform_uevent(struct device *dev, char **envp, int num_envp, struct platform_device *pdev = to_platform_device(dev); envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name); + snprintf(buffer, buffer_size, "MODALIAS=platform:%s", pdev->name); return 0; } diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 906bf5e8de89..e1a44020ed2b 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -23,6 +23,7 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pcspkr"); #ifdef CONFIG_X86 /* Use the global PIT lock ! */ diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 383107ba4bd3..f6722ba0dd1e 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -175,7 +175,6 @@ static int __init mst_pcmcia_init(void) if (!mst_pcmcia_device) return -ENOMEM; - mst_pcmcia_device->dev.uevent_suppress = 0; mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; ret = platform_device_add(mst_pcmcia_device); @@ -195,3 +194,4 @@ fs_initcall(mst_pcmcia_init); module_exit(mst_pcmcia_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index a2daa3f531b2..d5c33bd78d68 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -261,7 +261,6 @@ static int __init sharpsl_pcmcia_init(void) if (!sharpsl_pcmcia_device) return -ENOMEM; - sharpsl_pcmcia_device->dev.uevent_suppress = 0; sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; @@ -284,3 +283,4 @@ module_exit(sharpsl_pcmcia_exit); MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); -- cgit v1.2.3 From 8380770c842faef3001e44662953d64ad9a93663 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 30 Jul 2007 02:28:56 +0200 Subject: Driver core: make sysfs uevent-attributes static Attributes do not have an owner(module) anymore, so there is no need to carry the attributes in every single bus instance. Signed-off-by: Kay Sievers Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 61c67526a656..ff850d1b0d92 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -568,32 +568,29 @@ static void remove_bind_files(struct device_driver *drv) driver_remove_file(drv, &driver_attr_unbind); } +static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe); +static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO, + show_drivers_autoprobe, store_drivers_autoprobe); + static int add_probe_files(struct bus_type *bus) { int retval; - bus->drivers_probe_attr.attr.name = "drivers_probe"; - bus->drivers_probe_attr.attr.mode = S_IWUSR; - bus->drivers_probe_attr.store = store_drivers_probe; - retval = bus_create_file(bus, &bus->drivers_probe_attr); + retval = bus_create_file(bus, &bus_attr_drivers_probe); if (retval) goto out; - bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; - bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; - bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; - bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; - retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); + retval = bus_create_file(bus, &bus_attr_drivers_autoprobe); if (retval) - bus_remove_file(bus, &bus->drivers_probe_attr); + bus_remove_file(bus, &bus_attr_drivers_probe); out: return retval; } static void remove_probe_files(struct bus_type *bus) { - bus_remove_file(bus, &bus->drivers_autoprobe_attr); - bus_remove_file(bus, &bus->drivers_probe_attr); + bus_remove_file(bus, &bus_attr_drivers_autoprobe); + bus_remove_file(bus, &bus_attr_drivers_probe); } #else static inline int add_bind_files(struct device_driver *drv) { return 0; } -- cgit v1.2.3 From 7eff2e7a8b65c25920207324e56611150eb1cd9a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 14 Aug 2007 15:15:12 +0200 Subject: Driver core: change add_uevent_var to use a struct This changes the uevent buffer functions to use a struct instead of a long list of parameters. It does no longer require the caller to do the proper buffer termination and size accounting, which is currently wrong in some places. It fixes a known bug where parts of the uevent environment are overwritten because of wrong index calculations. Many thanks to Mathieu Desnoyers for finding bugs and improving the error handling. Signed-off-by: Kay Sievers Cc: Mathieu Desnoyers Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 16 +++--- drivers/amba/bus.c | 9 ++-- drivers/base/class.c | 42 ++++----------- drivers/base/core.c | 84 +++++++++-------------------- drivers/base/firmware_class.c | 11 ++-- drivers/base/memory.c | 3 +- drivers/base/platform.c | 6 +-- drivers/eisa/eisa-bus.c | 9 +--- drivers/firewire/fw-device.c | 11 +--- drivers/firmware/dmi-id.c | 17 +++--- drivers/i2c/i2c-core.c | 8 +-- drivers/ide/ide.c | 17 ++---- drivers/ieee1394/nodemgr.c | 17 ++---- drivers/infiniband/core/sysfs.c | 9 ++-- drivers/input/input.c | 62 +++++++-------------- drivers/input/serio/serio.c | 11 ++-- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 4 +- drivers/misc/tifm_core.c | 9 +--- drivers/mmc/core/bus.c | 21 +++----- drivers/pci/hotplug.c | 28 +++------- drivers/pci/pci-driver.c | 3 +- drivers/pci/pci.h | 3 +- drivers/pcmcia/cs.c | 10 ++-- drivers/pcmcia/ds.c | 26 +++------ drivers/power/power_supply.h | 3 +- drivers/power/power_supply_sysfs.c | 17 ++---- drivers/s390/cio/ccwgroup.c | 3 +- drivers/s390/cio/device.c | 25 +++------ drivers/s390/crypto/ap_bus.c | 14 ++--- drivers/scsi/scsi_sysfs.c | 9 +--- drivers/spi/spi.c | 7 +-- drivers/usb/core/driver.c | 29 +++------- drivers/usb/core/message.c | 28 +++------- drivers/w1/w1.c | 19 +++---- 34 files changed, 175 insertions(+), 415 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 64620d668742..5b4d462117cf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -319,16 +319,18 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } -static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct acpi_device *acpi_dev = to_acpi_device(dev); + int len; - strcpy(buffer, "MODALIAS="); - if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { - envp[0] = buffer; - envp[1] = NULL; - } + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += len; return 0; } diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 268e301775fc..6b94fb7be5f2 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG -static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) +static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) { struct amba_device *pcdev = to_amba_device(dev); - int retval = 0, i = 0, len = 0; + int retval = 0; - retval = add_uevent_var(envp, nr_env, &i, - buf, bufsz, &len, - "AMBA_ID=%08x", pcdev->periphid); - envp[i] = NULL; + retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); return retval; } #else diff --git a/drivers/base/class.c b/drivers/base/class.c index 4d2222618b78..ecd6336bffea 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -180,8 +180,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_uevent(struct class_device *class_dev, - char **envp, int num_envp, - char *buffer, int buffer_size) + struct kobj_uevent_env *env) { pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); return 0; @@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd) { } #endif -static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int class_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct class_device *class_dev = to_class_dev(kobj); struct device *dev = class_dev->dev; - int i = 0; - int length = 0; int retval = 0; pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); if (MAJOR(class_dev->devt)) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MAJOR=%u", MAJOR(class_dev->devt)); + add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt)); - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MINOR=%u", MINOR(class_dev->devt)); + add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt)); } if (dev) { const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); if (path) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); } if (dev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); } - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - if (class_dev->uevent) { /* have the class device specific function add its stuff */ - retval = class_dev->uevent(class_dev, envp, num_envp, - buffer, buffer_size); + retval = class_dev->uevent(class_dev, env); if (retval) 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->uevent(class_dev, envp, num_envp, - buffer, buffer_size); + retval = class_dev->class->uevent(class_dev, env); if (retval) pr_debug("class->uevent() returned %d\n", retval); } diff --git a/drivers/base/core.c b/drivers/base/core.c index ec86d6fc2360..d487c032dc4a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) return NULL; } -static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int dev_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct device *dev = to_dev(kobj); - int i = 0; - int length = 0; int retval = 0; /* add the major/minor if present */ if (MAJOR(dev->devt)) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MAJOR=%u", MAJOR(dev->devt)); - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MINOR=%u", MINOR(dev->devt)); + add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); + add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); } if (dev->type && dev->type->name) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVTYPE=%s", dev->type->name); + add_uevent_var(env, "DEVTYPE=%s", dev->type->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DRIVER=%s", dev->driver->name); + add_uevent_var(env, "DRIVER=%s", dev->driver->name); #ifdef CONFIG_SYSFS_DEPRECATED if (dev->class) { @@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, path = kobject_get_path(&parent->kobj, GFP_KERNEL); if (path) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); } - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", parent->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name); if (parent->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", parent->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", + parent->driver->name); } } else if (dev->bus) { - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); + add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); } #endif - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - + /* have the bus specific function add its stuff */ if (dev->bus && dev->bus->uevent) { - /* have the bus specific function add its stuff */ - retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->bus->uevent(dev, env); if (retval) pr_debug ("%s: bus uevent() returned %d\n", __FUNCTION__, retval); } + /* have the class specific function add its stuff */ if (dev->class && dev->class->dev_uevent) { - /* have the class specific function add its stuff */ - retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->class->dev_uevent(dev, env); if (retval) pr_debug("%s: class uevent() returned %d\n", __FUNCTION__, retval); } + /* have the device type specific fuction add its stuff */ if (dev->type && dev->type->uevent) { - /* have the device type specific fuction add its stuff */ - retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); + retval = dev->type->uevent(dev, env); if (retval) pr_debug("%s: dev_type uevent() returned %d\n", __FUNCTION__, retval); @@ -253,9 +227,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, { struct kobject *top_kobj; struct kset *kset; - char *envp[32]; - char *data = NULL; - char *pos; + struct kobj_uevent_env *env = NULL; int i; size_t count = 0; int retval; @@ -278,26 +250,20 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, if (!kset->uevent_ops->filter(kset, &dev->kobj)) goto out; - data = (char *)get_zeroed_page(GFP_KERNEL); - if (!data) + env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); + if (!env) return -ENOMEM; /* let the kset specific function add its keys */ - pos = data; - memset(envp, 0, sizeof(envp)); - retval = kset->uevent_ops->uevent(kset, &dev->kobj, - envp, ARRAY_SIZE(envp), - pos, PAGE_SIZE); + retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); if (retval) goto out; /* copy keys to file */ - for (i = 0; envp[i]; i++) { - pos = &buf[count]; - count += sprintf(pos, "%s\n", envp[i]); - } + for (i = 0; i < env->envp_idx; i++) + count += sprintf(&buf[count], "%s\n", env->envp[i]); out: - free_page((unsigned long)data); + kfree(env); return count; } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b24efd4e3e3d..4a1b9bfc5471 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -88,19 +88,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); static void fw_dev_release(struct device *dev); -static int firmware_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) { struct firmware_priv *fw_priv = dev_get_drvdata(dev); - int i = 0, len = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "FIRMWARE=%s", fw_priv->fw_id)) + if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "TIMEOUT=%i", loading_timeout)) + if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) return -ENOMEM; - envp[i] = NULL; return 0; } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 74b96795d2f5..cb99daeae936 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -34,8 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj) return MEMORY_CLASS_NAME; } -static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env) { int retval = 0; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9bfc434d1327..a2e3910196e0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -529,13 +529,11 @@ static struct device_attribute platform_dev_attrs[] = { __ATTR_NULL, }; -static int platform_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { struct platform_device *pdev = to_platform_device(dev); - envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=platform:%s", pdev->name); + add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); return 0; } diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index d944647c82c2..4d4a47393909 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -128,16 +128,11 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv) return 0; } -static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct eisa_device *edev = to_eisa_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); return 0; } diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2b6586341635..56681b3b297b 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -130,23 +130,16 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) } static int -fw_unit_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) { struct fw_unit *unit = fw_unit(dev); char modalias[64]; - int length = 0; - int i = 0; get_modalias(unit, modalias, sizeof(modalias)); - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=%s", modalias)) + if (add_uevent_var(env, "MODALIAS=%s", modalias)) return -ENOMEM; - envp[i] = NULL; - return 0; } diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 59c3b5aa89f4..2678098d4504 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -134,14 +134,17 @@ static struct attribute_group* sys_dmi_attribute_groups[] = { NULL }; -static int dmi_dev_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) { - strcpy(buffer, "MODALIAS="); - get_modalias(buffer+9, buffer_size-9); - envp[0] = buffer; - envp[1] = NULL; - + ssize_t len; + + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + len = get_modalias(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + if (len >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += len; return 0; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d663e6960d93..910a62de190d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -67,20 +67,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) #ifdef CONFIG_HOTPLUG /* uevent helps with hotplug: modprobe -q $(MODALIAS) */ -static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct i2c_client *client = to_i2c_client(dev); - int i = 0, length = 0; /* by definition, legacy drivers can't hotplug */ if (dev->driver || !client->driver_name) return 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=%s", client->driver_name)) + if (add_uevent_var(env, "MODALIAS=%s", client->driver_name)) return -ENOMEM; - envp[i] = NULL; dev_dbg(dev, "uevent\n"); return 0; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index e96212ce5729..a96a8b1b3539 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1663,20 +1663,13 @@ static struct device_attribute ide_dev_attrs[] = { __ATTR_NULL }; -static int ide_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) { 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; + + add_uevent_var(env, "MEDIA=%s", media_string(drive)); + add_uevent_var(env, "DRIVENAME=%s", drive->name); + add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); return 0; } diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2ffd53461db6..1939fee616ec 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -153,8 +153,7 @@ struct host_info { }; static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); 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); @@ -1160,12 +1159,9 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent #ifdef CONFIG_HOTPLUG -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { struct unit_directory *ud; - int i = 0; - int length = 0; int retval = 0; /* ieee1394:venNmoNspNverN */ char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; @@ -1180,9 +1176,7 @@ static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, #define PUT_ENVP(fmt,val) \ do { \ - retval = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &length, \ - fmt, val); \ + retval = add_uevent_var(env, fmt, val); \ if (retval) \ return retval; \ } while (0) @@ -1201,15 +1195,12 @@ do { \ #undef PUT_ENVP - envp[i] = NULL; - return 0; } #else -static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 70b77ae67422..3d4050681325 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -434,21 +434,18 @@ static void ib_device_release(struct class_device *cdev) kfree(dev); } -static int ib_device_uevent(struct class_device *cdev, char **envp, - int num_envp, char *buf, int size) +static int ib_device_uevent(struct class_device *cdev, + struct kobj_uevent_env *env) { struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); - int i = 0, len = 0; - if (add_uevent_var(envp, num_envp, &i, buf, size, &len, - "NAME=%s", dev->name)) + if (add_uevent_var(env, "NAME=%s", dev->name)) return -ENOMEM; /* * It would be nice to pass the node GUID with the event... */ - envp[i] = NULL; return 0; } diff --git a/drivers/input/input.c b/drivers/input/input.c index 5fe755586623..5dc361c954e2 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -859,87 +859,66 @@ static void input_dev_release(struct device *device) * Input uevent interface - loading event handlers based on * device bitfields. */ -static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_bm_var(struct kobj_uevent_env *env, const char *name, unsigned long *bitmap, int max) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "%s=", name)) return -ENOMEM; - *cur_len += input_print_bitmap(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - bitmap, max, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_bitmap(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + bitmap, max, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } -static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, struct input_dev *dev) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), - "MODALIAS="); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - *cur_len += input_print_modalias(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - dev, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_modalias(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + dev, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ + int err = add_uevent_var(env, fmt, val); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ do { \ - int err = input_add_uevent_bm_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - name, bm, max); \ + int err = input_add_uevent_bm_var(env, name, bm, max); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ do { \ - int err = input_add_uevent_modalias_var(envp, \ - num_envp, &i, \ - buffer, buffer_size, &len, \ - dev); \ + int err = input_add_uevent_modalias_var(env, dev); \ if (err) \ return err; \ } while (0) -static int input_dev_uevent(struct device *device, char **envp, - int num_envp, char *buffer, int buffer_size) +static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) { struct input_dev *dev = to_input_dev(device); - int i = 0; - int len = 0; INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", dev->id.bustype, dev->id.vendor, @@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp, INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); - envp[i] = NULL; return 0; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 372ca4931194..b3bc15acd3f5 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -876,18 +876,14 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) #define SERIO_ADD_UEVENT_VAR(fmt, val...) \ do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ + int err = add_uevent_var(env, fmt, val); \ if (err) \ return err; \ } while (0) -static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) { struct serio *serio; - int i = 0; - int len = 0; if (!dev) return -ENODEV; @@ -900,7 +896,6 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf 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; } @@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf #else -static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7a78d6b34738..2ee3c3049e8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -905,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, } -static int pvr2_sysfs_hotplug(struct device *cd,char **envp, - int numenvp,char *buf,int size) +static int pvr2_sysfs_hotplug(struct device *d, + struct kobj_uevent_env *env) { /* Even though we don't do anything here, we still need this function because sysfs will still try to call it. */ diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index d195fb088f4a..8f77949f93dd 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int tifm_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env) { struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); - int i = 0; - int length = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "TIFM_CARD_TYPE=%s", - tifm_media_type_name(sock->type, 1))) + if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1))) return -ENOMEM; return 0; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 8d6f6014870f..b0c22cad9423 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -58,12 +58,11 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv) } static int -mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, - int buf_size) +mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct mmc_card *card = dev_to_mmc_card(dev); const char *type; - int i = 0, length = 0; + int retval = 0; switch (card->type) { case MMC_TYPE_MMC: @@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, } if (type) { - if (add_uevent_var(envp, num_envp, &i, - buf, buf_size, &length, - "MMC_TYPE=%s", type)) - return -ENOMEM; + retval = add_uevent_var(env, "MMC_TYPE=%s", type); + if (retval) + return retval; } - if (add_uevent_var(envp, num_envp, &i, - buf, buf_size, &length, - "MMC_NAME=%s", mmc_card_name(card))) - return -ENOMEM; + retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); - envp[i] = NULL; - - return 0; + return retval; } static int mmc_bus_probe(struct device *dev) diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 1c97e7dd130b..2b5352a7dffc 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -3,12 +3,9 @@ #include #include "pci.h" -int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int pci_uevent(struct device *dev, struct kobj_uevent_env *env) { struct pci_dev *pdev; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp, if (!pdev) return -ENODEV; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_CLASS=%04X", pdev->class)) + if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) + if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, + if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PCI_SLOT_NAME=%s", pci_name(pdev))) + if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", + if (add_uevent_var(env, "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; - return 0; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 004bc2487270..f61be3abfdca 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -532,8 +532,7 @@ void pci_dev_put(struct pci_dev *dev) } #ifndef CONFIG_HOTPLUG -int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int pci_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4c36e80f6d26..b3a7d5b0f936 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,7 +1,6 @@ /* Functions internal to the PCI core code */ -extern int pci_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); extern void pci_cleanup_rom(struct pci_dev *dev); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f8b13f0270d7..a0aca46ce877 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -907,18 +907,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) EXPORT_SYMBOL(pcmcia_insert_card); -static int pcmcia_socket_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int pcmcia_socket_uevent(struct device *dev, + struct kobj_uevent_env *env) { struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); - int i = 0, length = 0; - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "SOCKET_NO=%u", s->sock)) + if (add_uevent_var(env, "SOCKET_NO=%u", s->sock)) return -ENOMEM; - envp[i] = NULL; - return 0; } diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a99607142fc8..55baa1f0fcbb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1064,11 +1064,10 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { #ifdef CONFIG_HOTPLUG -static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct pcmcia_device *p_dev; - int i, length = 0; + int i; u32 hash[4] = { 0, 0, 0, 0}; if (!dev) @@ -1083,23 +1082,13 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); } - i = 0; - - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "SOCKET_NO=%u", - p_dev->socket->sock)) + if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE_NO=%02X", - p_dev->device_no)) + if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" + if (add_uevent_var(env, "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, @@ -1112,15 +1101,12 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, hash[3])) return -ENOMEM; - envp[i] = NULL; - return 0; } #else -static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h index a9880d468ee4..f38ba482be75 100644 --- a/drivers/power/power_supply.h +++ b/drivers/power/power_supply.h @@ -14,8 +14,7 @@ extern int power_supply_create_attrs(struct power_supply *psy); extern void power_supply_remove_attrs(struct power_supply *psy); -extern int power_supply_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); +extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env); #else diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index de3155b21285..249f61bae639 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -195,11 +195,10 @@ static char *kstruprdup(const char *str, gfp_t gfp) return ret; } -int power_supply_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) { struct power_supply *psy = dev_get_drvdata(dev); - int i = 0, length = 0, ret = 0, j; + int ret = 0, j; char *prop_buf; char *attrname; @@ -212,8 +211,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_NAME=%s", psy->name); + ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name); if (ret) return ret; @@ -243,9 +241,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_%s=%s", - attrname, prop_buf); + ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); kfree(attrname); if (ret) goto out; @@ -282,14 +278,11 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "POWER_SUPPLY_%s=%s", - attrname, prop_buf); + ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); kfree(attrname); if (ret) goto out; } - envp[i] = NULL; out: free_page((unsigned long)prop_buf); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index b0a18f5176aa..5d967c439822 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -44,8 +44,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv) return 0; } static int -ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, - int buffer_size) +ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env) { /* TODO */ return 0; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e44d92eac8e9..606bb53e9fae 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -78,49 +78,38 @@ static int snprint_alias(char *buf, size_t size, /* Set up environment variables for ccw device uevent. Return 0 on success, * non-zero otherwise. */ -static int ccw_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ccw_device *cdev = to_ccwdev(dev); struct ccw_device_id *id = &(cdev->id); - int i = 0; - int len = 0; int ret; char modalias_buf[30]; /* CU_TYPE= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "CU_TYPE=%04X", id->cu_type); + ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type); if (ret) return ret; /* CU_MODEL= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "CU_MODEL=%02X", id->cu_model); + ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model); if (ret) return ret; /* The next two can be zero, that's ok for us */ /* DEV_TYPE= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "DEV_TYPE=%04X", id->dev_type); + ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type); if (ret) return ret; /* DEV_MODEL= */ - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "DEV_MODEL=%02X", id->dev_model); + ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model); if (ret) return ret; /* MODALIAS= */ snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); - ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "MODALIAS=%s", modalias_buf); - if (ret) - return ret; - envp[i] = NULL; - return 0; + ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf); + return ret; } struct bus_type ccw_bus_type; diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 90bd22014513..e99713041591 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -458,28 +458,22 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) * uevent function for AP devices. It sets up a single environment * variable DEV_TYPE which contains the hardware device type. */ -static int ap_uevent (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int ap_uevent (struct device *dev, struct kobj_uevent_env *env) { struct ap_device *ap_dev = to_ap_dev(dev); - int retval = 0, length = 0, i = 0; + int retval = 0; if (!ap_dev) return -ENODEV; /* Set up DEV_TYPE environment variable. */ - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEV_TYPE=%04X", ap_dev->device_type); + retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); if (retval) return retval; /* Add MODALIAS= */ - retval = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=ap:t%02X", ap_dev->device_type); + retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); - envp[i] = NULL; return retval; } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 34cdce6738a6..ede9986d349a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -277,16 +277,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct scsi_device *sdev = to_scsi_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e84d21597943..bcb8dd5fb0b4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; } -static int spi_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi = to_spi_device(dev); - envp[0] = buffer; - snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); - envp[1] = NULL; + add_uevent_var(env, "MODALIAS=%s", spi->modalias); return 0; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 63b1243a9139..6273a5197e6a 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -576,12 +576,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG -static int usb_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -610,51 +607,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, * all the device descriptors we don't tell them about. Or * act as usermode drivers. */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE=/proc/bus/usb/%03d/%03d", + if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", usb_dev->bus->busnum, usb_dev->devnum)) return -ENOMEM; #endif /* per-device configurations are common */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PRODUCT=%x/%x/%x", + if (add_uevent_var(env, "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_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "TYPE=%d/%d/%d", + if (add_uevent_var(env, "TYPE=%d/%d/%d", usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "BUSNUM=%03d", + if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVNUM=%03d", + if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) return -ENOMEM; - envp[i] = NULL; return 0; } #else -static int usb_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index d8f7b089a8f0..95a49d8efe7a 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1339,14 +1339,11 @@ void usb_release_interface(struct device *dev) } #ifdef CONFIG_HOTPLUG -static int usb_if_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; struct usb_interface *intf; struct usb_host_interface *alt; - int i = 0; - int length = 0; if (!dev) return -ENODEV; @@ -1359,39 +1356,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, alt = intf->cur_altsetting; #ifdef CONFIG_USB_DEVICEFS - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE=/proc/bus/usb/%03d/%03d", + if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", usb_dev->bus->busnum, usb_dev->devnum)) return -ENOMEM; #endif - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PRODUCT=%x/%x/%x", + if (add_uevent_var(env, "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; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "TYPE=%d/%d/%d", + if (add_uevent_var(env, "TYPE=%d/%d/%d", usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "INTERFACE=%d/%d/%d", + if (add_uevent_var(env, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, + if (add_uevent_var(env, "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), @@ -1404,14 +1392,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, alt->desc.bInterfaceProtocol)) return -ENOMEM; - envp[i] = NULL; return 0; } #else -static int usb_if_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index a593f900eff4..070217322c9f 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -197,7 +197,7 @@ static struct w1_family w1_default_family = { .fops = &w1_default_fops, }; -static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env); static struct bus_type w1_bus_type = { .name = "w1", @@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master) } #ifdef CONFIG_HOTPLUG -static int w1_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) { struct w1_master *md = NULL; struct w1_slave *sl = NULL; char *event_owner, *name; - int err, cur_index=0, cur_len=0; + int err; if (dev->driver == &w1_master_driver) { md = container_of(dev, struct w1_master, dev); @@ -423,23 +422,19 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, if (dev->driver != &w1_slave_driver || !sl) return 0; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_FID=%02X", sl->reg_num.family); + err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); if (err) return err; - err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, - &cur_len, "W1_SLAVE_ID=%024LX", - (unsigned long long)sl->reg_num.id); - envp[cur_index] = NULL; + err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", + (unsigned long long)sl->reg_num.id); if (err) return err; return 0; }; #else -static int w1_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) { return 0; } -- cgit v1.2.3 From 6a8d8abb6e4497ae4132a9b1f0a956ea501f1c46 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 15 Aug 2007 15:38:28 +0200 Subject: Driver core: add CONFIG_UEVENT_HELPER_PATH The kernel creates a process for every event that is send, even when there is no binary it could execute. We are needlessly creating around 200-300 failing processes during early bootup, until we have the chance to disable it from userspace. This change allows us to disable /sbin/hotplug entirely, if you want to, by setting UEVENT_HELPER_PATH="" in the kernel config. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 5d6312e33490..d7da109c24fd 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -1,5 +1,13 @@ menu "Generic Driver Options" +config UEVENT_HELPER_PATH + string "path to uevent helper" + depends on HOTPLUG + default "/sbin/hotplug" + help + Path to uevent helper program forked by the kernel for + every uevent. + config STANDALONE bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL default y -- cgit v1.2.3 From d6b05b84edf590ff872de6310ec20d60b5b37dd2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_set_kset This macro is only used by the driver core and is held over from when we had subsystems. It is not needed anymore. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 3 ++- drivers/base/class.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ff850d1b0d92..625f7e694521 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -823,7 +823,8 @@ int bus_register(struct bus_type * bus) if (retval) goto out; - subsys_set_kset(bus, bus_subsys); + bus->subsys.kobj.kset = &bus_subsys; + retval = subsystem_register(&bus->subsys); if (retval) goto out; diff --git a/drivers/base/class.c b/drivers/base/class.c index ecd6336bffea..cf9cf666f472 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -149,7 +149,7 @@ int class_register(struct class * cls) if (error) return error; - subsys_set_kset(cls, class_subsys); + cls->subsys.kobj.kset = &class_subsys; error = subsystem_register(&cls->subsys); if (!error) { -- cgit v1.2.3 From 27f20e5e4e60a7f28010eeb34399fe0cc9a1a235 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove kset_set_kset_s This macro is only used by the driver core and is held over from when we had subsystems. It is not needed anymore. Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 18febe26caa1..7ad893167823 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -139,7 +139,7 @@ int sysdev_class_register(struct sysdev_class * cls) kobject_name(&cls->kset.kobj)); INIT_LIST_HEAD(&cls->drivers); cls->kset.kobj.parent = &system_subsys.kobj; - kset_set_kset_s(cls, system_subsys); + cls->kset.kobj.kset = &system_subsys; return kset_register(&cls->kset); } -- cgit v1.2.3 From 6e9d930d167f8957a12a80515f3c417a98296378 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_put() There are no more subsystems, it's a kset now so remove the function and the only two users, which are in the driver core. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- drivers/base/class.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 625f7e694521..2f775936544b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -734,7 +734,7 @@ struct bus_type *get_bus(struct bus_type *bus) void put_bus(struct bus_type * bus) { - subsys_put(&bus->subsys); + kset_put(&bus->subsys); } diff --git a/drivers/base/class.c b/drivers/base/class.c index cf9cf666f472..50e34132576c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -100,7 +100,7 @@ static struct class *class_get(struct class *cls) static void class_put(struct class * cls) { if (cls) - subsys_put(&cls->subsys); + kset_put(&cls->subsys); } -- cgit v1.2.3 From 1ef4cfac01fb5e98900f5bdb2a722aac1daff11b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: Driver core: remove subsys_get() There are no more subsystems, it's a kset now so remove the function and the only two users, which are in the driver core. Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- drivers/base/class.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2f775936544b..bc38085dbb10 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -728,7 +728,7 @@ EXPORT_SYMBOL_GPL(device_reprobe); struct bus_type *get_bus(struct bus_type *bus) { - return bus ? container_of(subsys_get(&bus->subsys), + return bus ? container_of(kset_get(&bus->subsys), struct bus_type, subsys) : NULL; } diff --git a/drivers/base/class.c b/drivers/base/class.c index 50e34132576c..3e9b04c30fb9 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -93,7 +93,7 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr) static struct class *class_get(struct class *cls) { if (cls) - return container_of(subsys_get(&cls->subsys), struct class, subsys); + return container_of(kset_get(&cls->subsys), struct class, subsys); return NULL; } -- cgit v1.2.3 From fc1ede5888ab8a9b3e7f8567b945beed35222885 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2007 02:53:13 -0700 Subject: Driver core: remove put_bus() put_bus() should not be globally visable as it is not used by anything other than drivers/base/bus.c. This patch removes the visability of it, and renames it to match all of the other *_put() functions in the kernel. Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 1 - drivers/base/bus.c | 29 ++++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index 47eb02d9f1af..cebc7e754574 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -19,7 +19,6 @@ extern int bus_add_device(struct device * dev); extern void bus_attach_device(struct device * dev); extern void bus_remove_device(struct device * dev); extern struct bus_type *get_bus(struct bus_type * bus); -extern void put_bus(struct bus_type * bus); extern int bus_add_driver(struct device_driver *); extern void bus_remove_driver(struct device_driver *); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index bc38085dbb10..4f53b758ac2b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -30,6 +30,11 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, void *data); +static void bus_put(struct bus_type *bus) +{ + kset_put(&bus->subsys); +} + static ssize_t drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { @@ -124,7 +129,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) int error; if (get_bus(bus)) { error = sysfs_create_file(&bus->subsys.kobj, &attr-