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 <kay.sievers@vrfy.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Kay Sievers 2007-08-14 15:15:12 +02:00 committed by Greg Kroah-Hartman
parent 8380770c84
commit 7eff2e7a8b
47 changed files with 300 additions and 636 deletions

View file

@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
} }
static int tiocx_uevent(struct device *dev, char **envp, int num_envp, static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev,
return tsize; return tsize;
} }
int of_device_uevent(struct device *dev, int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
char **envp, int num_envp, char *buffer, int buffer_size)
{ {
struct of_device *ofdev; struct of_device *ofdev;
const char *compat; const char *compat;
int i = 0, length = 0, seen = 0, cplen, sl; int seen = 0, cplen, sl;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
ofdev = to_of_device(dev); ofdev = to_of_device(dev);
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name))
buffer, buffer_size, &length,
"OF_NAME=%s", ofdev->node->name))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type))
buffer, buffer_size, &length,
"OF_TYPE=%s", ofdev->node->type))
return -ENOMEM; return -ENOMEM;
/* Since the compatible field can contain pretty much anything /* Since the compatible field can contain pretty much anything
@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev,
compat = of_get_property(ofdev->node, "compatible", &cplen); compat = of_get_property(ofdev->node, "compatible", &cplen);
while (compat && *compat && cplen > 0) { while (compat && *compat && cplen > 0) {
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
buffer, buffer_size, &length,
"OF_COMPATIBLE_%d=%s", seen, compat))
return -ENOMEM; return -ENOMEM;
sl = strlen (compat) + 1; sl = strlen (compat) + 1;
@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev,
seen++; seen++;
} }
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
buffer, buffer_size, &length,
"OF_COMPATIBLE_N=%d", seen))
return -ENOMEM; return -ENOMEM;
/* modalias is trickier, we add it in 2 steps */ /* modalias is trickier, we add it in 2 steps */
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "MODALIAS="))
buffer, buffer_size, &length,
"MODALIAS="))
return -ENOMEM; return -ENOMEM;
sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
sl = of_device_get_modalias(ofdev, &buffer[length-1], sizeof(env->buf) - env->buflen);
buffer_size-length); if (sl >= (sizeof(env->buf) - env->buflen))
if (sl >= (buffer_size-length))
return -ENOMEM; return -ENOMEM;
env->buflen += sl;
length += sl;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
} }
static int vio_hotplug(struct device *dev, char **envp, int num_envp, static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
const struct vio_dev *vio_dev = to_vio_dev(dev); const struct vio_dev *vio_dev = to_vio_dev(dev);
struct device_node *dn; struct device_node *dn;
const char *cp; const char *cp;
int length;
if (!num_envp)
return -ENOMEM;
dn = dev->archdata.of_node; dn = dev->archdata.of_node;
if (!dn) if (!dn)
return -ENODEV; return -ENODEV;
cp = of_get_property(dn, "compatible", &length); cp = of_get_property(dn, "compatible", NULL);
if (!cp) if (!cp)
return -ENODEV; return -ENODEV;
envp[0] = buffer; add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
vio_dev->type, cp);
if ((buffer_size - length) <= 0)
return -ENOMEM;
envp[1] = NULL;
return 0; return 0;
} }

View file

@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev)
dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
} }
static int ps3_system_bus_uevent(struct device *_dev, char **envp, static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int i = 0, length = 0; int i = 0, length = 0;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
&length, "MODALIAS=ps3:%d",
dev->match_id))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -540,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
return ((ktype == &ktype_block) || (ktype == &ktype_part)); return ((ktype == &ktype_block) || (ktype == &ktype_part));
} }
static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp, static int block_uevent(struct kset *kset, struct kobject *kobj,
int num_envp, char *buffer, int buffer_size) struct kobj_uevent_env *env)
{ {
struct kobj_type *ktype = get_ktype(kobj); struct kobj_type *ktype = get_ktype(kobj);
struct device *physdev; struct device *physdev;
struct gendisk *disk; struct gendisk *disk;
struct hd_struct *part; struct hd_struct *part;
int length = 0;
int i = 0;
if (ktype == &ktype_block) { if (ktype == &ktype_block) {
disk = container_of(kobj, struct gendisk, kobj); disk = container_of(kobj, struct gendisk, kobj);
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, add_uevent_var(env, "MINOR=%u", disk->first_minor);
&length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) { } else if (ktype == &ktype_part) {
disk = container_of(kobj->parent, struct gendisk, kobj); disk = container_of(kobj->parent, struct gendisk, kobj);
part = container_of(kobj, struct hd_struct, kobj); part = container_of(kobj, struct hd_struct, kobj);
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, add_uevent_var(env, "MINOR=%u",
&length, "MINOR=%u",
disk->first_minor + part->partno); disk->first_minor + part->partno);
} else } else
return 0; return 0;
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, add_uevent_var(env, "MAJOR=%u", disk->major);
"MAJOR=%u", disk->major);
/* add physical device, backing this device */ /* add physical device, backing this device */
physdev = disk->driverfs_dev; physdev = disk->driverfs_dev;
if (physdev) { if (physdev) {
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, add_uevent_var(env, "PHYSDEVPATH=%s", path);
&length, "PHYSDEVPATH=%s", path);
kfree(path); kfree(path);
if (physdev->bus) if (physdev->bus)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name);
buffer, buffer_size, &length,
"PHYSDEVBUS=%s",
physdev->bus->name);
if (physdev->driver) if (physdev->driver)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, physdev->driver->name);
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s",
physdev->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;
return 0; return 0;
} }

View file

@ -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); return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
} }
static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_device *acpi_dev = to_acpi_device(dev);
int len;
strcpy(buffer, "MODALIAS="); if (add_uevent_var(env, "MODALIAS="))
if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { return -ENOMEM;
envp[0] = buffer; len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
envp[1] = NULL; sizeof(env->buf) - env->buflen);
} if (len >= (sizeof(env->buf) - env->buflen))
return -ENOMEM;
env->buflen += len;
return 0; return 0;
} }

View file

@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv)
} }
#ifdef CONFIG_HOTPLUG #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); 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, retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
buf, bufsz, &len,
"AMBA_ID=%08x", pcdev->periphid);
envp[i] = NULL;
return retval; return retval;
} }
#else #else

View file

@ -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 */ /* needed to allow these devices to have parent class devices */
static int class_device_create_uevent(struct class_device *class_dev, static int class_device_create_uevent(struct class_device *class_dev,
char **envp, int num_envp, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
return 0; return 0;
@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd)
{ } { }
#endif #endif
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, static int class_uevent(struct kset *kset, struct kobject *kobj,
int num_envp, char *buffer, int buffer_size) struct kobj_uevent_env *env)
{ {
struct class_device *class_dev = to_class_dev(kobj); struct class_device *class_dev = to_class_dev(kobj);
struct device *dev = class_dev->dev; struct device *dev = class_dev->dev;
int i = 0;
int length = 0;
int retval = 0; int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
if (MAJOR(class_dev->devt)) { if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
buffer, buffer_size, &length,
"MAJOR=%u", MAJOR(class_dev->devt));
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
buffer, buffer_size, &length,
"MINOR=%u", MINOR(class_dev->devt));
} }
if (dev) { if (dev) {
const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
if (path) { if (path) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVPATH=%s", path);
buffer, buffer_size, &length,
"PHYSDEVPATH=%s", path);
kfree(path); kfree(path);
} }
if (dev->bus) if (dev->bus)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver) if (dev->driver)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
buffer, buffer_size, &length,
"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) { if (class_dev->uevent) {
/* have the class device specific function add its stuff */ /* have the class device specific function add its stuff */
retval = class_dev->uevent(class_dev, envp, num_envp, retval = class_dev->uevent(class_dev, env);
buffer, buffer_size);
if (retval) if (retval)
pr_debug("class_dev->uevent() returned %d\n", retval); pr_debug("class_dev->uevent() returned %d\n", retval);
} else if (class_dev->class->uevent) { } else if (class_dev->class->uevent) {
/* have the class specific function add its stuff */ /* have the class specific function add its stuff */
retval = class_dev->class->uevent(class_dev, envp, num_envp, retval = class_dev->class->uevent(class_dev, env);
buffer, buffer_size);
if (retval) if (retval)
pr_debug("class->uevent() returned %d\n", retval); pr_debug("class->uevent() returned %d\n", retval);
} }

View file

@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
return NULL; return NULL;
} }
static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, static int dev_uevent(struct kset *kset, struct kobject *kobj,
int num_envp, char *buffer, int buffer_size) struct kobj_uevent_env *env)
{ {
struct device *dev = to_dev(kobj); struct device *dev = to_dev(kobj);
int i = 0;
int length = 0;
int retval = 0; int retval = 0;
/* add the major/minor if present */ /* add the major/minor if present */
if (MAJOR(dev->devt)) { if (MAJOR(dev->devt)) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
buffer, buffer_size, &length, add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
"MAJOR=%u", MAJOR(dev->devt));
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MINOR=%u", MINOR(dev->devt));
} }
if (dev->type && dev->type->name) if (dev->type && dev->type->name)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
buffer, buffer_size, &length,
"DEVTYPE=%s", dev->type->name);
if (dev->driver) if (dev->driver)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "DRIVER=%s", dev->driver->name);
buffer, buffer_size, &length,
"DRIVER=%s", dev->driver->name);
#ifdef CONFIG_SYSFS_DEPRECATED #ifdef CONFIG_SYSFS_DEPRECATED
if (dev->class) { 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); path = kobject_get_path(&parent->kobj, GFP_KERNEL);
if (path) { if (path) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVPATH=%s", path);
buffer, buffer_size, &length,
"PHYSDEVPATH=%s", path);
kfree(path); kfree(path);
} }
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", parent->bus->name);
if (parent->driver) if (parent->driver)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVDRIVER=%s",
buffer, buffer_size, &length, parent->driver->name);
"PHYSDEVDRIVER=%s", parent->driver->name);
} }
} else if (dev->bus) { } else if (dev->bus) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver) if (dev->driver)
add_uevent_var(envp, num_envp, &i, add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
} }
#endif #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;
if (dev->bus && dev->bus->uevent) {
/* have the bus specific function add its stuff */ /* have the bus specific function add its stuff */
retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); if (dev->bus && dev->bus->uevent) {
retval = dev->bus->uevent(dev, env);
if (retval) if (retval)
pr_debug ("%s: bus uevent() returned %d\n", pr_debug ("%s: bus uevent() returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
} }
if (dev->class && dev->class->dev_uevent) {
/* have the class specific function add its stuff */ /* have the class specific function add its stuff */
retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); if (dev->class && dev->class->dev_uevent) {
retval = dev->class->dev_uevent(dev, env);
if (retval) if (retval)
pr_debug("%s: class uevent() returned %d\n", pr_debug("%s: class uevent() returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
} }
if (dev->type && dev->type->uevent) {
/* have the device type specific fuction add its stuff */ /* have the device type specific fuction add its stuff */
retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); if (dev->type && dev->type->uevent) {
retval = dev->type->uevent(dev, env);
if (retval) if (retval)
pr_debug("%s: dev_type uevent() returned %d\n", pr_debug("%s: dev_type uevent() returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
@ -253,9 +227,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
{ {
struct kobject *top_kobj; struct kobject *top_kobj;
struct kset *kset; struct kset *kset;
char *envp[32]; struct kobj_uevent_env *env = NULL;
char *data = NULL;
char *pos;
int i; int i;
size_t count = 0; size_t count = 0;
int retval; 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)) if (!kset->uevent_ops->filter(kset, &dev->kobj))
goto out; goto out;
data = (char *)get_zeroed_page(GFP_KERNEL); env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
if (!data) if (!env)
return -ENOMEM; return -ENOMEM;
/* let the kset specific function add its keys */ /* let the kset specific function add its keys */
pos = data; retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
memset(envp, 0, sizeof(envp));
retval = kset->uevent_ops->uevent(kset, &dev->kobj,
envp, ARRAY_SIZE(envp),
pos, PAGE_SIZE);
if (retval) if (retval)
goto out; goto out;
/* copy keys to file */ /* copy keys to file */
for (i = 0; envp[i]; i++) { for (i = 0; i < env->envp_idx; i++)
pos = &buf[count]; count += sprintf(&buf[count], "%s\n", env->envp[i]);
count += sprintf(pos, "%s\n", envp[i]);
}
out: out:
free_page((unsigned long)data); kfree(env);
return count; return count;
} }

View file

@ -88,19 +88,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_dev_release(struct device *dev); static void fw_dev_release(struct device *dev);
static int firmware_uevent(struct device *dev, char **envp, int num_envp, static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct firmware_priv *fw_priv = dev_get_drvdata(dev); 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, if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
"FIRMWARE=%s", fw_priv->fw_id))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
"TIMEOUT=%i", loading_timeout))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -34,8 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
return MEMORY_CLASS_NAME; return MEMORY_CLASS_NAME;
} }
static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp, static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
int retval = 0; int retval = 0;

View file

@ -529,13 +529,11 @@ static struct device_attribute platform_dev_attrs[] = {
__ATTR_NULL, __ATTR_NULL,
}; };
static int platform_uevent(struct device *dev, char **envp, int num_envp, static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
envp[0] = buffer; add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
snprintf(buffer, buffer_size, "MODALIAS=platform:%s", pdev->name);
return 0; return 0;
} }

View file

@ -128,16 +128,11 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv)
return 0; return 0;
} }
static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp, static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct eisa_device *edev = to_eisa_device(dev); 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, add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
"MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -130,23 +130,16 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
} }
static int static int
fw_unit_uevent(struct device *dev, char **envp, int num_envp, fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct fw_unit *unit = fw_unit(dev); struct fw_unit *unit = fw_unit(dev);
char modalias[64]; char modalias[64];
int length = 0;
int i = 0;
get_modalias(unit, modalias, sizeof(modalias)); get_modalias(unit, modalias, sizeof(modalias));
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "MODALIAS=%s", modalias))
buffer, buffer_size, &length,
"MODALIAS=%s", modalias))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -134,14 +134,17 @@ static struct attribute_group* sys_dmi_attribute_groups[] = {
NULL NULL
}; };
static int dmi_dev_uevent(struct device *dev, char **envp, static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
strcpy(buffer, "MODALIAS="); ssize_t len;
get_modalias(buffer+9, buffer_size-9);
envp[0] = buffer;
envp[1] = NULL;
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; return 0;
} }

View file

@ -67,20 +67,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
/* uevent helps with hotplug: modprobe -q $(MODALIAS) */ /* uevent helps with hotplug: modprobe -q $(MODALIAS) */
static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int i = 0, length = 0;
/* by definition, legacy drivers can't hotplug */ /* by definition, legacy drivers can't hotplug */
if (dev->driver || !client->driver_name) if (dev->driver || !client->driver_name)
return 0; return 0;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
"MODALIAS=%s", client->driver_name))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
dev_dbg(dev, "uevent\n"); dev_dbg(dev, "uevent\n");
return 0; return 0;
} }

View file

@ -1663,20 +1663,13 @@ static struct device_attribute ide_dev_attrs[] = {
__ATTR_NULL __ATTR_NULL
}; };
static int ide_uevent(struct device *dev, char **envp, int num_envp, static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
ide_drive_t *drive = to_ide_device(dev); 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, add_uevent_var(env, "MEDIA=%s", media_string(drive));
"MEDIA=%s", media_string(drive)); add_uevent_var(env, "DRIVENAME=%s", drive->name);
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
"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; return 0;
} }

View file

@ -153,8 +153,7 @@ struct host_info {
}; };
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne); static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne); static void nodemgr_remove_ne(struct node_entry *ne);
static struct node_entry *find_entry_by_guid(u64 guid); 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 #ifdef CONFIG_HOTPLUG
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct unit_directory *ud; struct unit_directory *ud;
int i = 0;
int length = 0;
int retval = 0; int retval = 0;
/* ieee1394:venNmoNspNverN */ /* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; 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) \ #define PUT_ENVP(fmt,val) \
do { \ do { \
retval = add_uevent_var(envp, num_envp, &i, \ retval = add_uevent_var(env, fmt, val); \
buffer, buffer_size, &length, \
fmt, val); \
if (retval) \ if (retval) \
return retval; \ return retval; \
} while (0) } while (0)
@ -1201,15 +1195,12 @@ do { \
#undef PUT_ENVP #undef PUT_ENVP
envp[i] = NULL;
return 0; return 0;
} }
#else #else
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -434,21 +434,18 @@ static void ib_device_release(struct class_device *cdev)
kfree(dev); kfree(dev);
} }
static int ib_device_uevent(struct class_device *cdev, char **envp, static int ib_device_uevent(struct class_device *cdev,
int num_envp, char *buf, int size) struct kobj_uevent_env *env)
{ {
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 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, if (add_uevent_var(env, "NAME=%s", dev->name))
"NAME=%s", dev->name))
return -ENOMEM; return -ENOMEM;
/* /*
* It would be nice to pass the node GUID with the event... * It would be nice to pass the node GUID with the event...
*/ */
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -859,87 +859,66 @@ static void input_dev_release(struct device *device)
* Input uevent interface - loading event handlers based on * Input uevent interface - loading event handlers based on
* device bitfields. * device bitfields.
*/ */
static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
char *buffer, int buffer_size, int *cur_len,
const char *name, unsigned long *bitmap, int max) const char *name, unsigned long *bitmap, int max)
{ {
if (*cur_index >= num_envp - 1) int len;
if (add_uevent_var(env, "%s=", name))
return -ENOMEM; return -ENOMEM;
envp[*cur_index] = buffer + *cur_len; len = input_print_bitmap(&env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen,
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); bitmap, max, 0);
if (*cur_len >= buffer_size) if (len >= (sizeof(env->buf) - env->buflen))
return -ENOMEM; return -ENOMEM;
*cur_len += input_print_bitmap(buffer + *cur_len, env->buflen += len;
max(buffer_size - *cur_len, 0),
bitmap, max, 0) + 1;
if (*cur_len > buffer_size)
return -ENOMEM;
(*cur_index)++;
return 0; return 0;
} }
static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
char *buffer, int buffer_size, int *cur_len,
struct input_dev *dev) struct input_dev *dev)
{ {
if (*cur_index >= num_envp - 1) int len;
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM; return -ENOMEM;
envp[*cur_index] = buffer + *cur_len; len = input_print_modalias(&env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen,
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), dev, 0);
"MODALIAS="); if (len >= (sizeof(env->buf) - env->buflen))
if (*cur_len >= buffer_size)
return -ENOMEM; return -ENOMEM;
*cur_len += input_print_modalias(buffer + *cur_len, env->buflen += len;
max(buffer_size - *cur_len, 0),
dev, 0) + 1;
if (*cur_len > buffer_size)
return -ENOMEM;
(*cur_index)++;
return 0; return 0;
} }
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \ do { \
int err = add_uevent_var(envp, num_envp, &i, \ int err = add_uevent_var(env, fmt, val); \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \ if (err) \
return err; \ return err; \
} while (0) } while (0)
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
do { \ do { \
int err = input_add_uevent_bm_var(envp, num_envp, &i, \ int err = input_add_uevent_bm_var(env, name, bm, max); \
buffer, buffer_size, &len, \
name, bm, max); \
if (err) \ if (err) \
return err; \ return err; \
} while (0) } while (0)
#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
do { \ do { \
int err = input_add_uevent_modalias_var(envp, \ int err = input_add_uevent_modalias_var(env, dev); \
num_envp, &i, \
buffer, buffer_size, &len, \
dev); \
if (err) \ if (err) \
return err; \ return err; \
} while (0) } while (0)
static int input_dev_uevent(struct device *device, char **envp, static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
struct input_dev *dev = to_input_dev(device); struct input_dev *dev = to_input_dev(device);
int i = 0;
int len = 0;
INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
dev->id.bustype, dev->id.vendor, 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); INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -876,18 +876,14 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
#define SERIO_ADD_UEVENT_VAR(fmt, val...) \ #define SERIO_ADD_UEVENT_VAR(fmt, val...) \
do { \ do { \
int err = add_uevent_var(envp, num_envp, &i, \ int err = add_uevent_var(env, fmt, val); \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \ if (err) \
return err; \ return err; \
} while (0) } 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; struct serio *serio;
int i = 0;
int len = 0;
if (!dev) if (!dev)
return -ENODEV; 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("SERIO_EXTRA=%02x", serio->id.extra);
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
envp[i] = NULL;
return 0; return 0;
} }
@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
#else #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; return -ENODEV;
} }

View file

@ -905,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
} }
static int pvr2_sysfs_hotplug(struct device *cd,char **envp, static int pvr2_sysfs_hotplug(struct device *d,
int numenvp,char *buf,int size) struct kobj_uevent_env *env)
{ {
/* Even though we don't do anything here, we still need this function /* Even though we don't do anything here, we still need this function
because sysfs will still try to call it. */ because sysfs will still try to call it. */

View file

@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv)
return 0; return 0;
} }
static int tifm_uevent(struct device *dev, char **envp, int num_envp, static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); 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, if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
"TIFM_CARD_TYPE=%s",
tifm_media_type_name(sock->type, 1)))
return -ENOMEM; return -ENOMEM;
return 0; return 0;

View file

@ -58,12 +58,11 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
} }
static int static int
mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
int buf_size)
{ {
struct mmc_card *card = dev_to_mmc_card(dev); struct mmc_card *card = dev_to_mmc_card(dev);
const char *type; const char *type;
int i = 0, length = 0; int retval = 0;
switch (card->type) { switch (card->type) {
case MMC_TYPE_MMC: case MMC_TYPE_MMC:
@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
} }
if (type) { if (type) {
if (add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "MMC_TYPE=%s", type);
buf, buf_size, &length, if (retval)
"MMC_TYPE=%s", type)) return retval;
return -ENOMEM;
} }
if (add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
buf, buf_size, &length,
"MMC_NAME=%s", mmc_card_name(card)))
return -ENOMEM;
envp[i] = NULL; return retval;
return 0;
} }
static int mmc_bus_probe(struct device *dev) static int mmc_bus_probe(struct device *dev)

View file

@ -3,12 +3,9 @@
#include <linux/module.h> #include <linux/module.h>
#include "pci.h" #include "pci.h"
int pci_uevent(struct device *dev, char **envp, int num_envp, int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct pci_dev *pdev; struct pci_dev *pdev;
int i = 0;
int length = 0;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp,
if (!pdev) if (!pdev)
return -ENODEV; return -ENODEV;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
buffer, buffer_size, &length,
"PCI_CLASS=%04X", pdev->class))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
buffer, buffer_size, &length,
"PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
buffer, buffer_size, &length,
"PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
pdev->subsystem_device)) pdev->subsystem_device))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
buffer, buffer_size, &length,
"PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
buffer, buffer_size, &length,
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
pdev->vendor, pdev->device, pdev->vendor, pdev->device,
pdev->subsystem_vendor, pdev->subsystem_device, pdev->subsystem_vendor, pdev->subsystem_device,
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8), (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
(u8)(pdev->class))) (u8)(pdev->class)))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -532,8 +532,7 @@ void pci_dev_put(struct pci_dev *dev)
} }
#ifndef CONFIG_HOTPLUG #ifndef CONFIG_HOTPLUG
int pci_uevent(struct device *dev, char **envp, int num_envp, int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -1,7 +1,6 @@
/* Functions internal to the PCI core code */ /* Functions internal to the PCI core code */
extern int pci_uevent(struct device *dev, char **envp, int num_envp, extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
char *buffer, int buffer_size);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); 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_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev); extern void pci_cleanup_rom(struct pci_dev *dev);

View file

@ -907,18 +907,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
EXPORT_SYMBOL(pcmcia_insert_card); EXPORT_SYMBOL(pcmcia_insert_card);
static int pcmcia_socket_uevent(struct device *dev, char **envp, static int pcmcia_socket_uevent(struct device *dev,
int num_envp, char *buffer, int buffer_size) struct kobj_uevent_env *env)
{ {
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); 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, if (add_uevent_var(env, "SOCKET_NO=%u", s->sock))
&length, "SOCKET_NO=%u", s->sock))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -1064,11 +1064,10 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct pcmcia_device *p_dev; struct pcmcia_device *p_dev;
int i, length = 0; int i;
u32 hash[4] = { 0, 0, 0, 0}; u32 hash[4] = { 0, 0, 0, 0};
if (!dev) 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])); hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
} }
i = 0; if (add_uevent_var(env, "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; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
buffer, buffer_size, &length,
"DEVICE_NO=%02X",
p_dev->device_no))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
buffer, buffer_size, &length,
"MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
"pa%08Xpb%08Xpc%08Xpd%08X", "pa%08Xpb%08Xpc%08Xpd%08X",
p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_manf_id ? p_dev->manf_id : 0,
p_dev->has_card_id ? p_dev->card_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])) hash[3]))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }
#else #else
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -14,8 +14,7 @@
extern int power_supply_create_attrs(struct power_supply *psy); extern int power_supply_create_attrs(struct power_supply *psy);
extern void power_supply_remove_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, extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env);
char *buffer, int buffer_size);
#else #else

View file

@ -195,11 +195,10 @@ static char *kstruprdup(const char *str, gfp_t gfp)
return ret; return ret;
} }
int power_supply_uevent(struct device *dev, char **envp, int num_envp, int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct power_supply *psy = dev_get_drvdata(dev); struct power_supply *psy = dev_get_drvdata(dev);
int i = 0, length = 0, ret = 0, j; int ret = 0, j;
char *prop_buf; char *prop_buf;
char *attrname; 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); dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);
&length, "POWER_SUPPLY_NAME=%s", psy->name);
if (ret) if (ret)
return 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); dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
&length, "POWER_SUPPLY_%s=%s",
attrname, prop_buf);
kfree(attrname); kfree(attrname);
if (ret) if (ret)
goto out; 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); dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
&length, "POWER_SUPPLY_%s=%s",
attrname, prop_buf);
kfree(attrname); kfree(attrname);
if (ret) if (ret)
goto out; goto out;
} }
envp[i] = NULL;
out: out:
free_page((unsigned long)prop_buf); free_page((unsigned long)prop_buf);

View file

@ -44,8 +44,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
return 0; return 0;
} }
static int static int
ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
int buffer_size)
{ {
/* TODO */ /* TODO */
return 0; return 0;

View file

@ -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, /* Set up environment variables for ccw device uevent. Return 0 on success,
* non-zero otherwise. */ * non-zero otherwise. */
static int ccw_uevent(struct device *dev, char **envp, int num_envp, static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct ccw_device *cdev = to_ccwdev(dev); struct ccw_device *cdev = to_ccwdev(dev);
struct ccw_device_id *id = &(cdev->id); struct ccw_device_id *id = &(cdev->id);
int i = 0;
int len = 0;
int ret; int ret;
char modalias_buf[30]; char modalias_buf[30];
/* CU_TYPE= */ /* CU_TYPE= */
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type);
"CU_TYPE=%04X", id->cu_type);
if (ret) if (ret)
return ret; return ret;
/* CU_MODEL= */ /* CU_MODEL= */
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model);
"CU_MODEL=%02X", id->cu_model);
if (ret) if (ret)
return ret; return ret;
/* The next two can be zero, that's ok for us */ /* The next two can be zero, that's ok for us */
/* DEV_TYPE= */ /* DEV_TYPE= */
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type);
"DEV_TYPE=%04X", id->dev_type);
if (ret) if (ret)
return ret; return ret;
/* DEV_MODEL= */ /* DEV_MODEL= */
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model);
"DEV_MODEL=%02X", id->dev_model);
if (ret) if (ret)
return ret; return ret;
/* MODALIAS= */ /* MODALIAS= */
snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf);
"MODALIAS=%s", modalias_buf);
if (ret)
return ret; return ret;
envp[i] = NULL;
return 0;
} }
struct bus_type ccw_bus_type; struct bus_type ccw_bus_type;

View file

@ -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 * uevent function for AP devices. It sets up a single environment
* variable DEV_TYPE which contains the hardware device type. * variable DEV_TYPE which contains the hardware device type.
*/ */
static int ap_uevent (struct device *dev, char **envp, int num_envp, static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct ap_device *ap_dev = to_ap_dev(dev); struct ap_device *ap_dev = to_ap_dev(dev);
int retval = 0, length = 0, i = 0; int retval = 0;
if (!ap_dev) if (!ap_dev)
return -ENODEV; return -ENODEV;
/* Set up DEV_TYPE environment variable. */ /* Set up DEV_TYPE environment variable. */
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
buffer, buffer_size, &length,
"DEV_TYPE=%04X", ap_dev->device_type);
if (retval) if (retval)
return retval; return retval;
/* Add MODALIAS= */ /* Add MODALIAS= */
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
buffer, buffer_size, &length,
"MODALIAS=ap:t%02X", ap_dev->device_type);
envp[i] = NULL;
return retval; return retval;
} }

View file

@ -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; return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
} }
static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct scsi_device *sdev = to_scsi_device(dev); 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, add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
"MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -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; return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
} }
static int spi_uevent(struct device *dev, char **envp, int num_envp, static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
const struct spi_device *spi = to_spi_device(dev); const struct spi_device *spi = to_spi_device(dev);
envp[0] = buffer; add_uevent_var(env, "MODALIAS=%s", spi->modalias);
snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
envp[1] = NULL;
return 0; return 0;
} }

View file

@ -576,12 +576,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int usb_uevent(struct device *dev, char **envp, int num_envp, static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct usb_device *usb_dev; struct usb_device *usb_dev;
int i = 0;
int length = 0;
if (!dev) if (!dev)
return -ENODEV; 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 * all the device descriptors we don't tell them about. Or
* act as usermode drivers. * act as usermode drivers.
*/ */
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
buffer, buffer_size, &length,
"DEVICE=/proc/bus/usb/%03d/%03d",
usb_dev->bus->busnum, usb_dev->devnum)) usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM; return -ENOMEM;
#endif #endif
/* per-device configurations are common */ /* per-device configurations are common */
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
buffer, buffer_size, &length,
"PRODUCT=%x/%x/%x",
le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.idProduct),
le16_to_cpu(usb_dev->descriptor.bcdDevice))) le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM; return -ENOMEM;
/* class-based driver binding models */ /* class-based driver binding models */
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "TYPE=%d/%d/%d",
buffer, buffer_size, &length,
"TYPE=%d/%d/%d",
usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceClass,
usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceSubClass,
usb_dev->descriptor.bDeviceProtocol)) usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "BUSNUM=%03d",
buffer, buffer_size, &length,
"BUSNUM=%03d",
usb_dev->bus->busnum)) usb_dev->bus->busnum))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "DEVNUM=%03d",
buffer, buffer_size, &length,
"DEVNUM=%03d",
usb_dev->devnum)) usb_dev->devnum))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }
#else #else
static int usb_uevent(struct device *dev, char **envp, static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -1339,14 +1339,11 @@ void usb_release_interface(struct device *dev)
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int usb_if_uevent(struct device *dev, char **envp, int num_envp, static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct usb_device *usb_dev; struct usb_device *usb_dev;
struct usb_interface *intf; struct usb_interface *intf;
struct usb_host_interface *alt; struct usb_host_interface *alt;
int i = 0;
int length = 0;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
@ -1359,39 +1356,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
alt = intf->cur_altsetting; alt = intf->cur_altsetting;
#ifdef CONFIG_USB_DEVICEFS #ifdef CONFIG_USB_DEVICEFS
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
buffer, buffer_size, &length,
"DEVICE=/proc/bus/usb/%03d/%03d",
usb_dev->bus->busnum, usb_dev->devnum)) usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM; return -ENOMEM;
#endif #endif
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
buffer, buffer_size, &length,
"PRODUCT=%x/%x/%x",
le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.idProduct),
le16_to_cpu(usb_dev->descriptor.bcdDevice))) le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "TYPE=%d/%d/%d",
buffer, buffer_size, &length,
"TYPE=%d/%d/%d",
usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceClass,
usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceSubClass,
usb_dev->descriptor.bDeviceProtocol)) usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
buffer, buffer_size, &length,
"INTERFACE=%d/%d/%d",
alt->desc.bInterfaceClass, alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass, alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol)) alt->desc.bInterfaceProtocol))
return -ENOMEM; return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i, if (add_uevent_var(env,
buffer, buffer_size, &length,
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", "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.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct), 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)) alt->desc.bInterfaceProtocol))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }
#else #else
static int usb_if_uevent(struct device *dev, char **envp, static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
int num_envp, char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
} }

View file

@ -197,7 +197,7 @@ static struct w1_family w1_default_family = {
.fops = &w1_default_fops, .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 = { static struct bus_type w1_bus_type = {
.name = "w1", .name = "w1",
@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master)
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int w1_uevent(struct device *dev, char **envp, int num_envp, static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct w1_master *md = NULL; struct w1_master *md = NULL;
struct w1_slave *sl = NULL; struct w1_slave *sl = NULL;
char *event_owner, *name; char *event_owner, *name;
int err, cur_index=0, cur_len=0; int err;
if (dev->driver == &w1_master_driver) { if (dev->driver == &w1_master_driver) {
md = container_of(dev, struct w1_master, dev); 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) if (dev->driver != &w1_slave_driver || !sl)
return 0; return 0;
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family);
&cur_len, "W1_FID=%02X", sl->reg_num.family);
if (err) if (err)
return err; return err;
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, err = add_uevent_var(env, "W1_SLAVE_ID=%024LX",
&cur_len, "W1_SLAVE_ID=%024LX",
(unsigned long long)sl->reg_num.id); (unsigned long long)sl->reg_num.id);
envp[cur_index] = NULL;
if (err) if (err)
return err; return err;
return 0; return 0;
}; };
#else #else
static int w1_uevent(struct device *dev, char **envp, int num_envp, static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
return 0; return 0;
} }

View file

@ -20,7 +20,7 @@ struct of_device
extern ssize_t of_device_get_modalias(struct of_device *ofdev, extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len); char *str, ssize_t len);
extern int of_device_uevent(struct device *dev, extern int of_device_uevent(struct device *dev,
char **envp, int num_envp, char *buffer, int buffer_size); struct kobj_uevent_env *env);
/* This is just here during the transition */ /* This is just here during the transition */
#include <linux/of_device.h> #include <linux/of_device.h>

View file

@ -66,8 +66,7 @@ struct bus_type {
struct driver_attribute * drv_attrs; struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv); int (*match)(struct device * dev, struct device_driver * drv);
int (*uevent)(struct device *dev, char **envp, int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int num_envp, char *buffer, int buffer_size);
int (*probe)(struct device * dev); int (*probe)(struct device * dev);
int (*remove)(struct device * dev); int (*remove)(struct device * dev);
void (*shutdown)(struct device * dev); void (*shutdown)(struct device * dev);
@ -187,10 +186,8 @@ struct class {
struct class_device_attribute * class_dev_attrs; struct class_device_attribute * class_dev_attrs;
struct device_attribute * dev_attrs; struct device_attribute * dev_attrs;
int (*uevent)(struct class_device *dev, char **envp, int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
int num_envp, char *buffer, int buffer_size); int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*dev_uevent)(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
void (*release)(struct class_device *dev); void (*release)(struct class_device *dev);
void (*class_release)(struct class *class); void (*class_release)(struct class *class);
@ -266,8 +263,7 @@ struct class_device {
struct attribute_group ** groups; /* optional groups */ struct attribute_group ** groups; /* optional groups */
void (*release)(struct class_device *dev); void (*release)(struct class_device *dev);
int (*uevent)(struct class_device *dev, char **envp, int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
int num_envp, char *buffer, int buffer_size);
char class_id[BUS_ID_SIZE]; /* unique to this class */ char class_id[BUS_ID_SIZE]; /* unique to this class */
}; };
@ -335,8 +331,7 @@ extern void class_device_destroy(struct class *cls, dev_t devt);
struct device_type { struct device_type {
const char *name; const char *name;
struct attribute_group **groups; struct attribute_group **groups;
int (*uevent)(struct device *dev, char **envp, int num_envp, int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
char *buffer, int buffer_size);
void (*release)(struct device *dev); void (*release)(struct device *dev);
int (*suspend)(struct device * dev, pm_message_t state); int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev); int (*resume)(struct device * dev);

View file

@ -29,6 +29,8 @@
#define KOBJ_NAME_LEN 20 #define KOBJ_NAME_LEN 20
#define UEVENT_HELPER_PATH_LEN 256 #define UEVENT_HELPER_PATH_LEN 256
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
/* path to the userspace helper executed on an event */ /* path to the userspace helper executed on an event */
extern char uevent_helper[]; extern char uevent_helper[];
@ -111,11 +113,18 @@ struct kobj_type {
struct attribute ** default_attrs; struct attribute ** default_attrs;
}; };
struct kobj_uevent_env {
char *envp[UEVENT_NUM_ENVP];
int envp_idx;
char buf[UEVENT_BUFFER_SIZE];
int buflen;
};
struct kset_uevent_ops { struct kset_uevent_ops {
int (*filter)(struct kset *kset, struct kobject *kobj); int (*filter)(struct kset *kset, struct kobject *kobj);
const char *(*name)(struct kset *kset, struct kobject *kobj); const char *(*name)(struct kset *kset, struct kobject *kobj);
int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp, int (*uevent)(struct kset *kset, struct kobject *kobj,
int num_envp, char *buffer, int buffer_size); struct kobj_uevent_env *env);
}; };
/* /*
@ -275,10 +284,8 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action);
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp[]); char *envp[]);
int add_uevent_var(char **envp, int num_envp, int *cur_index, int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
char *buffer, int buffer_size, int *cur_len, __attribute__((format (printf, 2, 3)));
const char *format, ...)
__attribute__((format (printf, 7, 8)));
#else #else
static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{ return 0; } { return 0; }
@ -287,9 +294,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
char *envp[]) char *envp[])
{ return 0; } { return 0; }
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, static inline int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
{ return 0; } { return 0; }
#endif #endif

View file

@ -22,8 +22,6 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <net/sock.h> #include <net/sock.h>
#define BUFFER_SIZE 2048 /* buffer for the variables */
#define NUM_ENVP 32 /* number of env pointers */
/* the strings here must match the enum in include/linux/kobject.h */ /* the strings here must match the enum in include/linux/kobject.h */
const char *kobject_actions[] = { const char *kobject_actions[] = {
@ -56,29 +54,19 @@ static struct sock *uevent_sock;
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[]) char *envp_ext[])
{ {
char **envp; struct kobj_uevent_env *env;
char *buffer; const char *action_string = kobject_actions[action];
char *scratch;
const char *action_string;
const char *devpath = NULL; const char *devpath = NULL;
const char *subsystem; const char *subsystem;
struct kobject *top_kobj; struct kobject *top_kobj;
struct kset *kset; struct kset *kset;
struct kset_uevent_ops *uevent_ops; struct kset_uevent_ops *uevent_ops;
u64 seq; u64 seq;
char *seq_buff;
int i = 0; int i = 0;
int retval = 0; int retval = 0;
int j;
pr_debug("%s\n", __FUNCTION__); pr_debug("%s\n", __FUNCTION__);
action_string = kobject_actions[action];
if (!action_string) {
pr_debug("kobject attempted to send uevent without action_string!\n");
return -EINVAL;
}
/* search the kset we belong to */ /* search the kset we belong to */
top_kobj = kobj; top_kobj = kobj;
while (!top_kobj->kset && top_kobj->parent) { while (!top_kobj->kset && top_kobj->parent) {
@ -109,18 +97,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
return 0; return 0;
} }
/* environment index */ /* environment buffer */
envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
if (!envp) if (!env)
return -ENOMEM; return -ENOMEM;
/* environment values */
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!buffer) {
retval = -ENOMEM;
goto exit;
}
/* complete object path */ /* complete object path */
devpath = kobject_get_path(kobj, GFP_KERNEL); devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) { if (!devpath) {
@ -128,29 +109,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
goto exit; goto exit;
} }
/* event environemnt for helper process only */
envp[i++] = "HOME=/";
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
/* default keys */ /* default keys */
scratch = buffer; retval = add_uevent_var(env, "ACTION=%s", action_string);
envp [i++] = scratch; if (retval)
scratch += sprintf(scratch, "ACTION=%s", action_string) + 1; goto exit;
envp [i++] = scratch; retval = add_uevent_var(env, "DEVPATH=%s", devpath);
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; if (retval)
envp [i++] = scratch; goto exit;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
for (j = 0; envp_ext && envp_ext[j]; j++) if (retval)
envp[i++] = envp_ext[j]; goto exit;
/* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch; /* keys passed in from the caller */
scratch += strlen("SEQNUM=18446744073709551616") + 1; if (envp_ext) {
for (i = 0; envp_ext[i]; i++) {
retval = add_uevent_var(env, envp_ext[i]);
if (retval)
goto exit;
}
}
/* let the kset specific function add its stuff */ /* let the kset specific function add its stuff */
if (uevent_ops && uevent_ops->uevent) { if (uevent_ops && uevent_ops->uevent) {
retval = uevent_ops->uevent(kset, kobj, retval = uevent_ops->uevent(kset, kobj, env);
&envp[i], NUM_ENVP - i, scratch,
BUFFER_SIZE - (scratch - buffer));
if (retval) { if (retval) {
pr_debug ("%s - uevent() returned %d\n", pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
@ -158,11 +139,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
} }
} }
/* we will send an event, request a new sequence number */ /* we will send an event, so request a new sequence number */
spin_lock(&sequence_lock); spin_lock(&sequence_lock);
seq = ++uevent_seqnum; seq = ++uevent_seqnum;
spin_unlock(&sequence_lock); spin_unlock(&sequence_lock);
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq); retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
if (retval)
goto exit;
#if defined(CONFIG_NET) #if defined(CONFIG_NET)
/* send netlink message */ /* send netlink message */
@ -172,17 +155,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
/* allocate message with the maximum possible size */ /* allocate message with the maximum possible size */
len = strlen(action_string) + strlen(devpath) + 2; len = strlen(action_string) + strlen(devpath) + 2;
skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL); skb = alloc_skb(len + env->buflen, GFP_KERNEL);
if (skb) { if (skb) {
char *scratch;
/* add header */ /* add header */
scratch = skb_put(skb, len); scratch = skb_put(skb, len);
sprintf(scratch, "%s@%s", action_string, devpath); sprintf(scratch, "%s@%s", action_string, devpath);
/* copy keys to our continuous event payload buffer */ /* copy keys to our continuous event payload buffer */
for (i = 2; envp[i]; i++) { for (i = 0; i < env->envp_idx; i++) {
len = strlen(envp[i]) + 1; len = strlen(env->envp[i]) + 1;
scratch = skb_put(skb, len); scratch = skb_put(skb, len);
strcpy(scratch, envp[i]); strcpy(scratch, env->envp[i]);
} }
NETLINK_CB(skb).dst_group = 1; NETLINK_CB(skb).dst_group = 1;
@ -198,13 +183,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
argv [0] = uevent_helper; argv [0] = uevent_helper;
argv [1] = (char *)subsystem; argv [1] = (char *)subsystem;
argv [2] = NULL; argv [2] = NULL;
call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC); retval = add_uevent_var(env, "HOME=/");
if (retval)
goto exit;
retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
if (retval)
goto exit;
call_usermodehelper (argv[0], argv, env->envp, UMH_WAIT_EXEC);
} }
exit: exit:
kfree(devpath); kfree(devpath);
kfree(buffer); kfree(env);
kfree(envp);
return retval; return retval;
} }
@ -227,52 +218,38 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action)
EXPORT_SYMBOL_GPL(kobject_uevent); EXPORT_SYMBOL_GPL(kobject_uevent);
/** /**
* add_uevent_var - helper for creating event variables * add_uevent_var - add key value string to the environment buffer
* @envp: Pointer to table of environment variables, as passed into * @env: environment buffer structure
* uevent() method. * @format: printf format for the key=value pair
* @num_envp: Number of environment variable slots available, as
* passed into uevent() method.
* @cur_index: Pointer to current index into @envp. It should be
* 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 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_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 * Returns 0 if environment variable was added successfully or -ENOMEM
* if no space was available. * if no space was available.
*/ */
int add_uevent_var(char **envp, int num_envp, int *cur_index, int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
{ {
va_list args; va_list args;
int len;
/* if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
* We check against num_envp - 1 to make sure there is at printk(KERN_ERR "add_uevent_var: too many keys\n");
* least one slot left after we return, since kobject_uevent() WARN_ON(1);
* needs to set the last slot to NULL.
*/
if (*cur_index >= num_envp - 1)
return -ENOMEM; return -ENOMEM;
}
envp[*cur_index] = buffer + *cur_len;
va_start(args, format); va_start(args, format);
*cur_len += vsnprintf(envp[*cur_index], len = vsnprintf(&env->buf[env->buflen],
max(buffer_size - *cur_len, 0), sizeof(env->buf) - env->buflen,
format, args) + 1; format, args);
va_end(args); va_end(args);
if (*cur_len > buffer_size) if (len >= (sizeof(env->buf) - env->buflen)) {
printk(KERN_ERR "add_uevent_var: buffer size too small\n");
WARN_ON(1);
return -ENOMEM; return -ENOMEM;
}
(*cur_index)++; env->envp[env->envp_idx++] = &env->buf[env->buflen];
env->buflen += len + 1;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(add_uevent_var); EXPORT_SYMBOL_GPL(add_uevent_var);

View file

@ -105,10 +105,9 @@ static struct class_device_attribute *atm_attrs[] = {
NULL NULL
}; };
static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) static int atm_uevent(struct class_device *cdev, struct kobj_uevent_env *env)
{ {
struct atm_dev *adev; struct atm_dev *adev;
int i = 0, len = 0;
if (!cdev) if (!cdev)
return -ENODEV; return -ENODEV;
@ -117,11 +116,9 @@ static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char
if (!adev) if (!adev)
return -ENODEV; return -ENODEV;
if (add_uevent_var(envp, num_envp, &i, buf, size, &len, if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number))
"NAME=%s%d", adev->type, adev->number))
return -ENOMEM; return -ENOMEM;
envp[i] = NULL;
return 0; return 0;
} }

View file

@ -396,28 +396,22 @@ static struct attribute_group wireless_group = {
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int netdev_uevent(struct device *d, char **envp, static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
int num_envp, char *buf, int size)
{ {
struct net_device *dev = to_net_dev(d); struct net_device *dev = to_net_dev(d);
int retval, len = 0, i = 0; int retval;
/* pass interface to uevent. */ /* pass interface to uevent. */
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
buf, size, &len,
"INTERFACE=%s", dev->name);
if (retval) if (retval)
goto exit; goto exit;
/* pass ifindex to uevent. /* pass ifindex to uevent.
* ifindex is useful as it won't change (interface name may change) * ifindex is useful as it won't change (interface name may change)
* and is what RtNetlink uses natively. */ * and is what RtNetlink uses natively. */
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex);
buf, size, &len,
"IFINDEX=%d", dev->ifindex);
exit: exit:
envp[i] = NULL;
return retval; return retval;
} }
#endif #endif

View file

@ -53,8 +53,7 @@ static void wiphy_dev_release(struct device *dev)
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int wiphy_uevent(struct device *dev, char **envp, static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
int num_envp, char *buf, int size)
{ {
/* TODO, we probably need stuff here */ /* TODO, we probably need stuff here */
return 0; return 0;

View file

@ -56,13 +56,12 @@ static int soundbus_probe(struct device *dev)
} }
static int soundbus_uevent(struct device *dev, char **envp, int num_envp, static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env)
char *buffer, int buffer_size)
{ {
struct soundbus_dev * soundbus_dev; struct soundbus_dev * soundbus_dev;
struct of_device * of; struct of_device * of;
const char *compat; const char *compat;
int retval = 0, i = 0, length = 0; int retval = 0;
int cplen, seen = 0; int cplen, seen = 0;
if (!dev) if (!dev)
@ -75,15 +74,11 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
of = &soundbus_dev->ofdev; of = &soundbus_dev->ofdev;
/* stuff we want to pass to /sbin/hotplug */ /* stuff we want to pass to /sbin/hotplug */
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "OF_NAME=%s", of->node->name);
buffer, buffer_size, &length,
"OF_NAME=%s", of->node->name);
if (retval) if (retval)
return retval; return retval;
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "OF_TYPE=%s", of->node->type);
buffer, buffer_size, &length,
"OF_TYPE=%s", of->node->type);
if (retval) if (retval)
return retval; return retval;
@ -93,27 +88,19 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
compat = of_get_property(of->node, "compatible", &cplen); compat = of_get_property(of->node, "compatible", &cplen);
while (compat && cplen > 0) { while (compat && cplen > 0) {
int tmp = length; int tmp = env->buflen;
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
buffer, buffer_size, &length,
"OF_COMPATIBLE_%d=%s", seen, compat);
if (retval) if (retval)
return retval; return retval;
compat += length - tmp; compat += env->buflen - tmp;
cplen -= length - tmp; cplen -= env->buflen - tmp;
seen += 1; seen += 1;
} }
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
buffer, buffer_size, &length,
"OF_COMPATIBLE_N=%d", seen);
if (retval) if (retval)
return retval; return retval;
retval = add_uevent_var(envp, num_envp, &i, retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias);
buffer, buffer_size, &length,
"MODALIAS=%s", soundbus_dev->modalias);
envp[i] = NULL;
return retval; return retval;
} }