aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2007-08-14 09:15:12 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:51:01 -0400
commit7eff2e7a8b65c25920207324e56611150eb1cd9a (patch)
tree02a0eeba9d25d996233e30c18f258dfae0ae2139
parent8380770c842faef3001e44662953d64ad9a93663 (diff)
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>
-rw-r--r--arch/ia64/sn/kernel/tiocx.c3
-rw-r--r--arch/powerpc/kernel/of_device.c37
-rw-r--r--arch/powerpc/kernel/vio.c16
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c9
-rw-r--r--block/genhd.c35
-rw-r--r--drivers/acpi/scan.c16
-rw-r--r--drivers/amba/bus.c9
-rw-r--r--drivers/base/class.c42
-rw-r--r--drivers/base/core.c84
-rw-r--r--drivers/base/firmware_class.c11
-rw-r--r--drivers/base/memory.c3
-rw-r--r--drivers/base/platform.c6
-rw-r--r--drivers/eisa/eisa-bus.c9
-rw-r--r--drivers/firewire/fw-device.c11
-rw-r--r--drivers/firmware/dmi-id.c17
-rw-r--r--drivers/i2c/i2c-core.c8
-rw-r--r--drivers/ide/ide.c17
-rw-r--r--drivers/ieee1394/nodemgr.c17
-rw-r--r--drivers/infiniband/core/sysfs.c9
-rw-r--r--drivers/input/input.c62
-rw-r--r--drivers/input/serio/serio.c11
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c4
-rw-r--r--drivers/misc/tifm_core.c9
-rw-r--r--drivers/mmc/core/bus.c21
-rw-r--r--drivers/pci/hotplug.c28
-rw-r--r--drivers/pci/pci-driver.c3
-rw-r--r--drivers/pci/pci.h3
-rw-r--r--drivers/pcmcia/cs.c10
-rw-r--r--drivers/pcmcia/ds.c26
-rw-r--r--drivers/power/power_supply.h3
-rw-r--r--drivers/power/power_supply_sysfs.c17
-rw-r--r--drivers/s390/cio/ccwgroup.c3
-rw-r--r--drivers/s390/cio/device.c25
-rw-r--r--drivers/s390/crypto/ap_bus.c14
-rw-r--r--drivers/scsi/scsi_sysfs.c9
-rw-r--r--drivers/spi/spi.c7
-rw-r--r--drivers/usb/core/driver.c29
-rw-r--r--drivers/usb/core/message.c28
-rw-r--r--drivers/w1/w1.c19
-rw-r--r--include/asm-powerpc/of_device.h2
-rw-r--r--include/linux/device.h15
-rw-r--r--include/linux/kobject.h23
-rw-r--r--lib/kobject_uevent.c149
-rw-r--r--net/atm/atm_sysfs.c7
-rw-r--r--net/core/net-sysfs.c14
-rw-r--r--net/wireless/sysfs.c3
-rw-r--r--sound/aoa/soundbus/core.c33
47 files changed, 300 insertions, 636 deletions
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 5a289e4de838..a88eba3314d7 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
66 66
67} 67}
68 68
69static int tiocx_uevent(struct device *dev, char **envp, int num_envp, 69static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
70 char *buffer, int buffer_size)
71{ 70{
72 return -ENODEV; 71 return -ENODEV;
73} 72}
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 89b911e83c04..8f3db32fac8b 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev,
57 return tsize; 57 return tsize;
58} 58}
59 59
60int of_device_uevent(struct device *dev, 60int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
61 char **envp, int num_envp, char *buffer, int buffer_size)
62{ 61{
63 struct of_device *ofdev; 62 struct of_device *ofdev;
64 const char *compat; 63 const char *compat;
65 int i = 0, length = 0, seen = 0, cplen, sl; 64 int seen = 0, cplen, sl;
66 65
67 if (!dev) 66 if (!dev)
68 return -ENODEV; 67 return -ENODEV;
69 68
70 ofdev = to_of_device(dev); 69 ofdev = to_of_device(dev);
71 70
72 if (add_uevent_var(envp, num_envp, &i, 71 if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name))
73 buffer, buffer_size, &length,
74 "OF_NAME=%s", ofdev->node->name))
75 return -ENOMEM; 72 return -ENOMEM;
76 73
77 if (add_uevent_var(envp, num_envp, &i, 74 if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type))
78 buffer, buffer_size, &length,
79 "OF_TYPE=%s", ofdev->node->type))
80 return -ENOMEM; 75 return -ENOMEM;
81 76
82 /* Since the compatible field can contain pretty much anything 77 /* Since the compatible field can contain pretty much anything
@@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev,
85 80
86 compat = of_get_property(ofdev->node, "compatible", &cplen); 81 compat = of_get_property(ofdev->node, "compatible", &cplen);
87 while (compat && *compat && cplen > 0) { 82 while (compat && *compat && cplen > 0) {
88 if (add_uevent_var(envp, num_envp, &i, 83 if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
89 buffer, buffer_size, &length,
90 "OF_COMPATIBLE_%d=%s", seen, compat))
91 return -ENOMEM; 84 return -ENOMEM;
92 85
93 sl = strlen (compat) + 1; 86 sl = strlen (compat) + 1;
@@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev,
96 seen++; 89 seen++;
97 } 90 }
98 91
99 if (add_uevent_var(envp, num_envp, &i, 92 if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
100 buffer, buffer_size, &length,
101 "OF_COMPATIBLE_N=%d", seen))
102 return -ENOMEM; 93 return -ENOMEM;
103 94
104 /* modalias is trickier, we add it in 2 steps */ 95 /* modalias is trickier, we add it in 2 steps */
105 if (add_uevent_var(envp, num_envp, &i, 96 if (add_uevent_var(env, "MODALIAS="))
106 buffer, buffer_size, &length,
107 "MODALIAS="))
108 return -ENOMEM; 97 return -ENOMEM;
109 98 sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
110 sl = of_device_get_modalias(ofdev, &buffer[length-1], 99 sizeof(env->buf) - env->buflen);
111 buffer_size-length); 100 if (sl >= (sizeof(env->buf) - env->buflen))
112 if (sl >= (buffer_size-length))
113 return -ENOMEM; 101 return -ENOMEM;
114 102 env->buflen += sl;
115 length += sl;
116
117 envp[i] = NULL;
118 103
119 return 0; 104 return 0;
120} 105}
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index cb22a3557c4e..19a5656001c0 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
317 return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); 317 return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
318} 318}
319 319
320static int vio_hotplug(struct device *dev, char **envp, int num_envp, 320static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
321 char *buffer, int buffer_size)
322{ 321{
323 const struct vio_dev *vio_dev = to_vio_dev(dev); 322 const struct vio_dev *vio_dev = to_vio_dev(dev);
324 struct device_node *dn; 323 struct device_node *dn;
325 const char *cp; 324 const char *cp;
326 int length;
327
328 if (!num_envp)
329 return -ENOMEM;
330 325
331 dn = dev->archdata.of_node; 326 dn = dev->archdata.of_node;
332 if (!dn) 327 if (!dn)
333 return -ENODEV; 328 return -ENODEV;
334 cp = of_get_property(dn, "compatible", &length); 329 cp = of_get_property(dn, "compatible", NULL);
335 if (!cp) 330 if (!cp)
336 return -ENODEV; 331 return -ENODEV;
337 332
338 envp[0] = buffer; 333 add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
339 length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
340 vio_dev->type, cp);
341 if ((buffer_size - length) <= 0)
342 return -ENOMEM;
343 envp[1] = NULL;
344 return 0; 334 return 0;
345} 335}
346 336
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 4bb634a17e43..ea0b2c790412 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev)
437 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 437 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
438} 438}
439 439
440static int ps3_system_bus_uevent(struct device *_dev, char **envp, 440static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
441 int num_envp, char *buffer, int buffer_size)
442{ 441{
443 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 442 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
444 int i = 0, length = 0; 443 int i = 0, length = 0;
445 444
446 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 445 if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
447 &length, "MODALIAS=ps3:%d",
448 dev->match_id))
449 return -ENOMEM; 446 return -ENOMEM;
450
451 envp[i] = NULL;
452 return 0; 447 return 0;
453} 448}
454 449
diff --git a/block/genhd.c b/block/genhd.c
index 3af1e7a378d4..e609996f2e76 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -540,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
540 return ((ktype == &ktype_block) || (ktype == &ktype_part)); 540 return ((ktype == &ktype_block) || (ktype == &ktype_part));
541} 541}
542 542
543static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp, 543static int block_uevent(struct kset *kset, struct kobject *kobj,
544 int num_envp, char *buffer, int buffer_size) 544 struct kobj_uevent_env *env)
545{ 545{
546 struct kobj_type *ktype = get_ktype(kobj); 546 struct kobj_type *ktype = get_ktype(kobj);
547 struct device *physdev; 547 struct device *physdev;
548 struct gendisk *disk; 548 struct gendisk *disk;
549 struct hd_struct *part; 549 struct hd_struct *part;
550 int length = 0;
551 int i = 0;
552 550
553 if (ktype == &ktype_block) { 551 if (ktype == &ktype_block) {
554 disk = container_of(kobj, struct gendisk, kobj); 552 disk = container_of(kobj, struct gendisk, kobj);
555 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 553 add_uevent_var(env, "MINOR=%u", disk->first_minor);
556 &length, "MINOR=%u", disk->first_minor);
557 } else if (ktype == &ktype_part) { 554 } else if (ktype == &ktype_part) {
558 disk = container_of(kobj->parent, struct gendisk, kobj); 555 disk = container_of(kobj->parent, struct gendisk, kobj);
559 part = container_of(kobj, struct hd_struct, kobj); 556 part = container_of(kobj, struct hd_struct, kobj);
560 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 557 add_uevent_var(env, "MINOR=%u",
561 &length, "MINOR=%u",
562 disk->first_minor + part->partno); 558 disk->first_minor + part->partno);
563 } else 559 } else
564 return 0; 560 return 0;
565 561
566 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 562 add_uevent_var(env, "MAJOR=%u", disk->major);
567 "MAJOR=%u", disk->major);
568 563
569 /* add physical device, backing this device */ 564 /* add physical device, backing this device */
570 physdev = disk->driverfs_dev; 565 physdev = disk->driverfs_dev;
571 if (physdev) { 566 if (physdev) {
572 char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); 567 char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
573 568
574 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 569 add_uevent_var(env, "PHYSDEVPATH=%s", path);
575 &length, "PHYSDEVPATH=%s", path);
576 kfree(path); 570 kfree(path);
577 571
578 if (physdev->bus) 572 if (physdev->bus)
579 add_uevent_var(envp, num_envp, &i, 573 add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name);
580 buffer, buffer_size, &length,
581 "PHYSDEVBUS=%s",
582 physdev->bus->name);
583 574
584 if (physdev->driver) 575 if (physdev->driver)
585 add_uevent_var(envp, num_envp, &i, 576 add_uevent_var(env, physdev->driver->name);
586 buffer, buffer_size, &length,
587 "PHYSDEVDRIVER=%s",
588 physdev->driver->name);
589 } 577 }
590 578
591 /* terminate, set to next free slot, shrink available space */
592 envp[i] = NULL;
593 envp = &envp[i];
594 num_envp -= i;
595 buffer = &buffer[length];
596 buffer_size -= length;
597
598 return 0; 579 return 0;
599} 580}
600 581
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)
319 return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); 319 return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
320} 320}
321 321
322static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, 322static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
323 char *buffer, int buffer_size)
324{ 323{
325 struct acpi_device *acpi_dev = to_acpi_device(dev); 324 struct acpi_device *acpi_dev = to_acpi_device(dev);
325 int len;
326 326
327 strcpy(buffer, "MODALIAS="); 327 if (add_uevent_var(env, "MODALIAS="))
328 if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { 328 return -ENOMEM;
329 envp[0] = buffer; 329 len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
330 envp[1] = NULL; 330 sizeof(env->buf) - env->buflen);
331 } 331 if (len >= (sizeof(env->buf) - env->buflen))
332 return -ENOMEM;
333 env->buflen += len;
332 return 0; 334 return 0;
333} 335}
334 336
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)
44} 44}
45 45
46#ifdef CONFIG_HOTPLUG 46#ifdef CONFIG_HOTPLUG
47static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) 47static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
48{ 48{
49 struct amba_device *pcdev = to_amba_device(dev); 49 struct amba_device *pcdev = to_amba_device(dev);
50 int retval = 0, i = 0, len = 0; 50 int retval = 0;
51 51
52 retval = add_uevent_var(envp, nr_env, &i, 52 retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
53 buf, bufsz, &len,
54 "AMBA_ID=%08x", pcdev->periphid);
55 envp[i] = NULL;
56 return retval; 53 return retval;
57} 54}
58#else 55#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)
180 180
181/* needed to allow these devices to have parent class devices */ 181/* needed to allow these devices to have parent class devices */
182static int class_device_create_uevent(struct class_device *class_dev, 182static int class_device_create_uevent(struct class_device *class_dev,
183 char **envp, int num_envp, 183 struct kobj_uevent_env *env)
184 char *buffer, int buffer_size)
185{ 184{
186 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); 185 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
187 return 0; 186 return 0;
@@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd)
403{ } 402{ }
404#endif 403#endif
405 404
406static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, 405static int class_uevent(struct kset *kset, struct kobject *kobj,
407 int num_envp, char *buffer, int buffer_size) 406 struct kobj_uevent_env *env)
408{ 407{
409 struct class_device *class_dev = to_class_dev(kobj); 408 struct class_device *class_dev = to_class_dev(kobj);
410 struct device *dev = class_dev->dev; 409 struct device *dev = class_dev->dev;
411 int i = 0;
412 int length = 0;
413 int retval = 0; 410 int retval = 0;
414 411
415 pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); 412 pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
416 413
417 if (MAJOR(class_dev->devt)) { 414 if (MAJOR(class_dev->devt)) {
418 add_uevent_var(envp, num_envp, &i, 415 add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
419 buffer, buffer_size, &length,
420 "MAJOR=%u", MAJOR(class_dev->devt));
421 416
422 add_uevent_var(envp, num_envp, &i, 417 add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
423 buffer, buffer_size, &length,
424 "MINOR=%u", MINOR(class_dev->devt));
425 } 418 }
426 419
427 if (dev) { 420 if (dev) {
428 const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); 421 const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
429 if (path) { 422 if (path) {
430 add_uevent_var(envp, num_envp, &i, 423 add_uevent_var(env, "PHYSDEVPATH=%s", path);
431 buffer, buffer_size, &length,
432 "PHYSDEVPATH=%s", path);
433 kfree(path); 424 kfree(path);
434 } 425 }
435 426
436 if (dev->bus) 427 if (dev->bus)
437 add_uevent_var(envp, num_envp, &i, 428 add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
438 buffer, buffer_size, &length,
439 "PHYSDEVBUS=%s", dev->bus->name);
440 429
441 if (dev->driver) 430 if (dev->driver)
442 add_uevent_var(envp, num_envp, &i, 431 add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
443 buffer, buffer_size, &length,
444 "PHYSDEVDRIVER=%s", dev->driver->name);
445 } 432 }
446 433
447 /* terminate, set to next free slot, shrink available space */
448 envp[i] = NULL;
449 envp = &envp[i];
450 num_envp -= i;
451 buffer = &buffer[length];
452 buffer_size -= length;
453
454 if (class_dev->uevent) { 434 if (class_dev->uevent) {
455 /* have the class device specific function add its stuff */ 435 /* have the class device specific function add its stuff */
456 retval = class_dev->uevent(class_dev, envp, num_envp, 436 retval = class_dev->uevent(class_dev, env);
457 buffer, buffer_size);
458 if (retval) 437 if (retval)
459 pr_debug("class_dev->uevent() returned %d\n", retval); 438 pr_debug("class_dev->uevent() returned %d\n", retval);
460 } else if (class_dev->class->uevent) { 439 } else if (class_dev->class->uevent) {
461 /* have the class specific function add its stuff */ 440 /* have the class specific function add its stuff */
462 retval = class_dev->class->uevent(class_dev, envp, num_envp, 441 retval = class_dev->class->uevent(class_dev, env);
463 buffer, buffer_size);
464 if (retval) 442 if (retval)
465 pr_debug("class->uevent() returned %d\n", retval); 443 pr_debug("class->uevent() returned %d\n", retval);
466 } 444 }
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)
141 return NULL; 141 return NULL;
142} 142}
143 143
144static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, 144static int dev_uevent(struct kset *kset, struct kobject *kobj,
145 int num_envp, char *buffer, int buffer_size) 145 struct kobj_uevent_env *env)
146{ 146{
147 struct device *dev = to_dev(kobj); 147 struct device *dev = to_dev(kobj);
148 int i = 0;
149 int length = 0;
150 int retval = 0; 148 int retval = 0;
151 149
152 /* add the major/minor if present */ 150 /* add the major/minor if present */
153 if (MAJOR(dev->devt)) { 151 if (MAJOR(dev->devt)) {
154 add_uevent_var(envp, num_envp, &i, 152 add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
155 buffer, buffer_size, &length, 153 add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
156 "MAJOR=%u", MAJOR(dev->devt));
157 add_uevent_var(envp, num_envp, &i,
158 buffer, buffer_size, &length,
159 "MINOR=%u", MINOR(dev->devt));
160 } 154 }
161 155
162 if (dev->type && dev->type->name) 156 if (dev->type && dev->type->name)
163 add_uevent_var(envp, num_envp, &i, 157 add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
164 buffer, buffer_size, &length,
165 "DEVTYPE=%s", dev->type->name);
166 158
167 if (dev->driver) 159 if (dev->driver)
168 add_uevent_var(envp, num_envp, &i, 160 add_uevent_var(env, "DRIVER=%s", dev->driver->name);
169 buffer, buffer_size, &length,
170 "DRIVER=%s", dev->driver->name);
171 161
172#ifdef CONFIG_SYSFS_DEPRECATED 162#ifdef CONFIG_SYSFS_DEPRECATED
173 if (dev->class) { 163 if (dev->class) {
@@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
181 171
182 path = kobject_get_path(&parent->kobj, GFP_KERNEL); 172 path = kobject_get_path(&parent->kobj, GFP_KERNEL);
183 if (path) { 173 if (path) {
184 add_uevent_var(envp, num_envp, &i, 174 add_uevent_var(env, "PHYSDEVPATH=%s", path);
185 buffer, buffer_size, &length,
186 "PHYSDEVPATH=%s", path);
187 kfree(path); 175 kfree(path);
188 } 176 }
189 177
190 add_uevent_var(envp, num_envp, &i, 178 add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
191 buffer, buffer_size, &length,
192 "PHYSDEVBUS=%s", parent->bus->name);
193 179
194 if (parent->driver) 180 if (parent->driver)
195 add_uevent_var(envp, num_envp, &i, 181 add_uevent_var(env, "PHYSDEVDRIVER=%s",
196 buffer, buffer_size, &length, 182 parent->driver->name);
197 "PHYSDEVDRIVER=%s", parent->driver->name);
198 } 183 }
199 } else if (dev->bus) { 184 } else if (dev->bus) {
200 add_uevent_var(envp, num_envp, &i, 185 add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
201 buffer, buffer_size, &length,
202 "PHYSDEVBUS=%s", dev->bus->name);
203 186
204 if (dev->driver) 187 if (dev->driver)
205 add_uevent_var(envp, num_envp, &i, 188 add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
206 buffer, buffer_size, &length,
207 "PHYSDEVDRIVER=%s", dev->driver->name);
208 } 189 }
209#endif 190#endif
210 191
211 /* terminate, set to next free slot, shrink available space */ 192 /* have the bus specific function add its stuff */
212 envp[i] = NULL;
213 envp = &envp[i];
214 num_envp -= i;
215 buffer = &buffer[length];
216 buffer_size -= length;
217
218 if (dev->bus && dev->bus->uevent) { 193 if (dev->bus && dev->bus->uevent) {
219 /* have the bus specific function add its stuff */ 194 retval = dev->bus->uevent(dev, env);
220 retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
221 if (retval) 195 if (retval)
222 pr_debug ("%s: bus uevent() returned %d\n", 196 pr_debug ("%s: bus uevent() returned %d\n",
223 __FUNCTION__, retval); 197 __FUNCTION__, retval);
224 } 198 }
225 199
200 /* have the class specific function add its stuff */
226 if (dev->class && dev->class->dev_uevent) { 201 if (dev->class && dev->class->dev_uevent) {
227 /* have the class specific function add its stuff */ 202 retval = dev->class->dev_uevent(dev, env);
228 retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
229 if (retval) 203 if (retval)
230 pr_debug("%s: class uevent() returned %d\n", 204 pr_debug("%s: class uevent() returned %d\n",
231 __FUNCTION__, retval); 205 __FUNCTION__, retval);
232 } 206 }
233 207
208 /* have the device type specific fuction add its stuff */
234 if (dev->type && dev->type->uevent) { 209 if (dev->type && dev->type->uevent) {
235 /* have the device type specific fuction add its stuff */ 210 retval = dev->type->uevent(dev, env);
236 retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
237 if (retval) 211 if (retval)
238 pr_debug("%s: dev_type uevent() returned %d\n", 212 pr_debug("%s: dev_type uevent() returned %d\n",
239 __FUNCTION__, retval); 213 __FUNCTION__, retval);
@@ -253,9 +227,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
253{ 227{
254 struct kobject *top_kobj; 228 struct kobject *top_kobj;
255 struct kset *kset; 229 struct kset *kset;
256 char *envp[32]; 230 struct kobj_uevent_env *env = NULL;
257 char *data = NULL;
258 char *pos;
259 int i; 231 int i;
260 size_t count = 0; 232 size_t count = 0;
261 int retval; 233 int retval;
@@ -278,26 +250,20 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
278 if (!kset->uevent_ops->filter(kset, &dev->kobj)) 250 if (!kset->uevent_ops->filter(kset, &dev->kobj))
279 goto out; 251 goto out;
280 252
281 data = (char *)get_zeroed_page(GFP_KERNEL); 253 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
282 if (!data) 254 if (!env)
283 return -ENOMEM; 255 return -ENOMEM;
284 256
285 /* let the kset specific function add its keys */ 257 /* let the kset specific function add its keys */
286 pos = data; 258 retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
287 memset(envp, 0, sizeof(envp));
288 retval = kset->uevent_ops->uevent(kset, &dev->kobj,
289 envp, ARRAY_SIZE(envp),
290 pos, PAGE_SIZE);
291 if (retval) 259 if (retval)
292 goto out; 260 goto out;
293 261
294 /* copy keys to file */ 262 /* copy keys to file */
295 for (i = 0; envp[i]; i++) { 263 for (i = 0; i < env->envp_idx; i++)
296 pos = &buf[count]; 264 count += sprintf(&buf[count], "%s\n", env->envp[i]);
297 count += sprintf(pos, "%s\n", envp[i]);
298 }
299out: 265out:
300 free_page((unsigned long)data); 266 kfree(env);
301 return count; 267 return count;
302} 268}
303 269
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);
88 88
89static void fw_dev_release(struct device *dev); 89static void fw_dev_release(struct device *dev);
90 90
91static int firmware_uevent(struct device *dev, char **envp, int num_envp, 91static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
92 char *buffer, int buffer_size)
93{ 92{
94 struct firmware_priv *fw_priv = dev_get_drvdata(dev); 93 struct firmware_priv *fw_priv = dev_get_drvdata(dev);
95 int i = 0, len = 0;
96 94
97 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 95 if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
98 "FIRMWARE=%s", fw_priv->fw_id))
99 return -ENOMEM; 96 return -ENOMEM;
100 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 97 if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
101 "TIMEOUT=%i", loading_timeout))
102 return -ENOMEM; 98 return -ENOMEM;
103 envp[i] = NULL;
104 99
105 return 0; 100 return 0;
106} 101}
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)
34 return MEMORY_CLASS_NAME; 34 return MEMORY_CLASS_NAME;
35} 35}
36 36
37static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp, 37static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env)
38 int num_envp, char *buffer, int buffer_size)
39{ 38{
40 int retval = 0; 39 int retval = 0;
41 40
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[] = {
529 __ATTR_NULL, 529 __ATTR_NULL,
530}; 530};
531 531
532static int platform_uevent(struct device *dev, char **envp, int num_envp, 532static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
533 char *buffer, int buffer_size)
534{ 533{
535 struct platform_device *pdev = to_platform_device(dev); 534 struct platform_device *pdev = to_platform_device(dev);
536 535
537 envp[0] = buffer; 536 add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
538 snprintf(buffer, buffer_size, "MODALIAS=platform:%s", pdev->name);
539 return 0; 537 return 0;
540} 538}
541 539
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)
128 return 0; 128 return 0;
129} 129}
130 130
131static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp, 131static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
132 char *buffer, int buffer_size)
133{ 132{
134 struct eisa_device *edev = to_eisa_device(dev); 133 struct eisa_device *edev = to_eisa_device(dev);
135 int i = 0;
136 int length = 0;
137 134
138 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 135 add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
139 "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
140 envp[i] = NULL;
141 return 0; 136 return 0;
142} 137}
143 138
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)
130} 130}
131 131
132static int 132static int
133fw_unit_uevent(struct device *dev, char **envp, int num_envp, 133fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
134 char *buffer, int buffer_size)
135{ 134{
136 struct fw_unit *unit = fw_unit(dev); 135 struct fw_unit *unit = fw_unit(dev);
137 char modalias[64]; 136 char modalias[64];
138 int length = 0;
139 int i = 0;
140 137
141 get_modalias(unit, modalias, sizeof(modalias)); 138 get_modalias(unit, modalias, sizeof(modalias));
142 139
143 if (add_uevent_var(envp, num_envp, &i, 140 if (add_uevent_var(env, "MODALIAS=%s", modalias))
144 buffer, buffer_size, &length,
145 "MODALIAS=%s", modalias))
146 return -ENOMEM; 141 return -ENOMEM;
147 142
148 envp[i] = NULL;
149
150 return 0; 143 return 0;
151} 144}
152 145
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[] = {
134 NULL 134 NULL
135}; 135};
136 136
137static int dmi_dev_uevent(struct device *dev, char **envp, 137static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
138 int num_envp, char *buffer, int buffer_size)
139{ 138{
140 strcpy(buffer, "MODALIAS="); 139 ssize_t len;
141 get_modalias(buffer+9, buffer_size-9); 140
142 envp[0] = buffer; 141 if (add_uevent_var(env, "MODALIAS="))
143 envp[1] = NULL; 142 return -ENOMEM;
144 143 len = get_modalias(&env->buf[env->buflen - 1],
144 sizeof(env->buf) - env->buflen);
145 if (len >= (sizeof(env->buf) - env->buflen))
146 return -ENOMEM;
147 env->buflen += len;
145 return 0; 148 return 0;
146} 149}
147 150
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)
67#ifdef CONFIG_HOTPLUG 67#ifdef CONFIG_HOTPLUG
68 68
69/* uevent helps with hotplug: modprobe -q $(MODALIAS) */ 69/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
70static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, 70static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
71 char *buffer, int buffer_size)
72{ 71{
73 struct i2c_client *client = to_i2c_client(dev); 72 struct i2c_client *client = to_i2c_client(dev);
74 int i = 0, length = 0;
75 73
76 /* by definition, legacy drivers can't hotplug */ 74 /* by definition, legacy drivers can't hotplug */
77 if (dev->driver || !client->driver_name) 75 if (dev->driver || !client->driver_name)
78 return 0; 76 return 0;
79 77
80 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 78 if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
81 "MODALIAS=%s", client->driver_name))
82 return -ENOMEM; 79 return -ENOMEM;
83 envp[i] = NULL;
84 dev_dbg(dev, "uevent\n"); 80 dev_dbg(dev, "uevent\n");
85 return 0; 81 return 0;
86} 82}
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[] = {
1663 __ATTR_NULL 1663 __ATTR_NULL
1664}; 1664};
1665 1665
1666static int ide_uevent(struct device *dev, char **envp, int num_envp, 1666static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
1667 char *buffer, int buffer_size)
1668{ 1667{
1669 ide_drive_t *drive = to_ide_device(dev); 1668 ide_drive_t *drive = to_ide_device(dev);
1670 int i = 0; 1669
1671 int length = 0; 1670 add_uevent_var(env, "MEDIA=%s", media_string(drive));
1672 1671 add_uevent_var(env, "DRIVENAME=%s", drive->name);
1673 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 1672 add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
1674 "MEDIA=%s", media_string(drive));
1675 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
1676 "DRIVENAME=%s", drive->name);
1677 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
1678 "MODALIAS=ide:m-%s", media_string(drive));
1679 envp[i] = NULL;
1680 return 0; 1673 return 0;
1681} 1674}
1682 1675
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 {
153}; 153};
154 154
155static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); 155static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
156static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, 156static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
157 char *buffer, int buffer_size);
158static void nodemgr_resume_ne(struct node_entry *ne); 157static void nodemgr_resume_ne(struct node_entry *ne);
159static void nodemgr_remove_ne(struct node_entry *ne); 158static void nodemgr_remove_ne(struct node_entry *ne);
160static struct node_entry *find_entry_by_guid(u64 guid); 159static 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
1160 1159
1161#ifdef CONFIG_HOTPLUG 1160#ifdef CONFIG_HOTPLUG
1162 1161
1163static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, 1162static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
1164 char *buffer, int buffer_size)
1165{ 1163{
1166 struct unit_directory *ud; 1164 struct unit_directory *ud;
1167 int i = 0;
1168 int length = 0;
1169 int retval = 0; 1165 int retval = 0;
1170 /* ieee1394:venNmoNspNverN */ 1166 /* ieee1394:venNmoNspNverN */
1171 char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; 1167 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,
1180 1176
1181#define PUT_ENVP(fmt,val) \ 1177#define PUT_ENVP(fmt,val) \
1182do { \ 1178do { \
1183 retval = add_uevent_var(envp, num_envp, &i, \ 1179 retval = add_uevent_var(env, fmt, val); \
1184 buffer, buffer_size, &length, \
1185 fmt, val); \
1186 if (retval) \ 1180 if (retval) \
1187 return retval; \ 1181 return retval; \
1188} while (0) 1182} while (0)
@@ -1201,15 +1195,12 @@ do { \
1201 1195
1202#undef PUT_ENVP 1196#undef PUT_ENVP
1203 1197
1204 envp[i] = NULL;
1205
1206 return 0; 1198 return 0;
1207} 1199}
1208 1200
1209#else 1201#else
1210 1202
1211static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, 1203static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
1212 char *buffer, int buffer_size)
1213{ 1204{
1214 return -ENODEV; 1205 return -ENODEV;
1215} 1206}
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)
434 kfree(dev); 434 kfree(dev);
435} 435}
436 436
437static int ib_device_uevent(struct class_device *cdev, char **envp, 437static int ib_device_uevent(struct class_device *cdev,
438 int num_envp, char *buf, int size) 438 struct kobj_uevent_env *env)
439{ 439{
440 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 440 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
441 int i = 0, len = 0;
442 441
443 if (add_uevent_var(envp, num_envp, &i, buf, size, &len, 442 if (add_uevent_var(env, "NAME=%s", dev->name))
444 "NAME=%s", dev->name))
445 return -ENOMEM; 443 return -ENOMEM;
446 444
447 /* 445 /*
448 * It would be nice to pass the node GUID with the event... 446 * It would be nice to pass the node GUID with the event...
449 */ 447 */
450 448
451 envp[i] = NULL;
452 return 0; 449 return 0;
453} 450}
454 451
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)
859 * Input uevent interface - loading event handlers based on 859 * Input uevent interface - loading event handlers based on
860 * device bitfields. 860 * device bitfields.
861 */ 861 */
862static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, 862static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
863 char *buffer, int buffer_size, int *cur_len,
864 const char *name, unsigned long *bitmap, int max) 863 const char *name, unsigned long *bitmap, int max)
865{ 864{
866 if (*cur_index >= num_envp - 1) 865 int len;
867 return -ENOMEM;
868
869 envp[*cur_index] = buffer + *cur_len;
870 866
871 *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); 867 if (add_uevent_var(env, "%s=", name))
872 if (*cur_len >= buffer_size)
873 return -ENOMEM; 868 return -ENOMEM;
874 869
875 *cur_len += input_print_bitmap(buffer + *cur_len, 870 len = input_print_bitmap(&env->buf[env->buflen - 1],
876 max(buffer_size - *cur_len, 0), 871 sizeof(env->buf) - env->buflen,
877 bitmap, max, 0) + 1; 872 bitmap, max, 0);
878 if (*cur_len > buffer_size) 873 if (len >= (sizeof(env->buf) - env->buflen))
879 return -ENOMEM; 874 return -ENOMEM;
880 875
881 (*cur_index)++; 876 env->buflen += len;
882 return 0; 877 return 0;
883} 878}
884 879
885static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, 880static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
886 char *buffer, int buffer_size, int *cur_len,
887 struct input_dev *dev) 881 struct input_dev *dev)
888{ 882{
889 if (*cur_index >= num_envp - 1) 883 int len;
890 return -ENOMEM;
891
892 envp[*cur_index] = buffer + *cur_len;
893 884
894 *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), 885 if (add_uevent_var(env, "MODALIAS="))
895 "MODALIAS=");
896 if (*cur_len >= buffer_size)
897 return -ENOMEM; 886 return -ENOMEM;
898 887
899 *cur_len += input_print_modalias(buffer + *cur_len, 888 len = input_print_modalias(&env->buf[env->buflen - 1],
900 max(buffer_size - *cur_len, 0), 889 sizeof(env->buf) - env->buflen,
901 dev, 0) + 1; 890 dev, 0);
902 if (*cur_len > buffer_size) 891 if (len >= (sizeof(env->buf) - env->buflen))
903 return -ENOMEM; 892 return -ENOMEM;
904 893
905 (*cur_index)++; 894 env->buflen += len;
906 return 0; 895 return 0;
907} 896}
908 897
909#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ 898#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
910 do { \ 899 do { \
911 int err = add_uevent_var(envp, num_envp, &i, \ 900 int err = add_uevent_var(env, fmt, val); \
912 buffer, buffer_size, &len, \
913 fmt, val); \
914 if (err) \ 901 if (err) \
915 return err; \ 902 return err; \
916 } while (0) 903 } while (0)
917 904
918#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ 905#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
919 do { \ 906 do { \
920 int err = input_add_uevent_bm_var(envp, num_envp, &i, \ 907 int err = input_add_uevent_bm_var(env, name, bm, max); \
921 buffer, buffer_size, &len, \
922 name, bm, max); \
923 if (err) \ 908 if (err) \
924 return err; \ 909 return err; \
925 } while (0) 910 } while (0)
926 911
927#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ 912#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
928 do { \ 913 do { \
929 int err = input_add_uevent_modalias_var(envp, \ 914 int err = input_add_uevent_modalias_var(env, dev); \
930 num_envp, &i, \
931 buffer, buffer_size, &len, \
932 dev); \
933 if (err) \ 915 if (err) \
934 return err; \ 916 return err; \
935 } while (0) 917 } while (0)
936 918
937static int input_dev_uevent(struct device *device, char **envp, 919static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
938 int num_envp, char *buffer, int buffer_size)
939{ 920{
940 struct input_dev *dev = to_input_dev(device); 921 struct input_dev *dev = to_input_dev(device);
941 int i = 0;
942 int len = 0;
943 922
944 INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", 923 INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
945 dev->id.bustype, dev->id.vendor, 924 dev->id.bustype, dev->id.vendor,
@@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp,
971 950
972 INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); 951 INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
973 952
974 envp[i] = NULL;
975 return 0; 953 return 0;
976} 954}
977 955
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)
876 876
877#define SERIO_ADD_UEVENT_VAR(fmt, val...) \ 877#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
878 do { \ 878 do { \
879 int err = add_uevent_var(envp, num_envp, &i, \ 879 int err = add_uevent_var(env, fmt, val); \
880 buffer, buffer_size, &len, \
881 fmt, val); \
882 if (err) \ 880 if (err) \
883 return err; \ 881 return err; \
884 } while (0) 882 } while (0)
885 883
886static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) 884static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
887{ 885{
888 struct serio *serio; 886 struct serio *serio;
889 int i = 0;
890 int len = 0;
891 887
892 if (!dev) 888 if (!dev)
893 return -ENODEV; 889 return -ENODEV;
@@ -900,7 +896,6 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
900 SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); 896 SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
901 SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", 897 SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
902 serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); 898 serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
903 envp[i] = NULL;
904 899
905 return 0; 900 return 0;
906} 901}
@@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
908 903
909#else 904#else
910 905
911static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) 906static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
912{ 907{
913 return -ENODEV; 908 return -ENODEV;
914} 909}
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,
905} 905}
906 906
907 907
908static int pvr2_sysfs_hotplug(struct device *cd,char **envp, 908static int pvr2_sysfs_hotplug(struct device *d,
909 int numenvp,char *buf,int size) 909 struct kobj_uevent_env *env)
910{ 910{
911 /* Even though we don't do anything here, we still need this function 911 /* Even though we don't do anything here, we still need this function
912 because sysfs will still try to call it. */ 912 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)
57 return 0; 57 return 0;
58} 58}
59 59
60static int tifm_uevent(struct device *dev, char **envp, int num_envp, 60static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
61 char *buffer, int buffer_size)
62{ 61{
63 struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); 62 struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
64 int i = 0;
65 int length = 0;
66 63
67 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 64 if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
68 "TIFM_CARD_TYPE=%s",
69 tifm_media_type_name(sock->type, 1)))
70 return -ENOMEM; 65 return -ENOMEM;
71 66
72 return 0; 67 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)
58} 58}
59 59
60static int 60static int
61mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 61mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
62 int buf_size)
63{ 62{
64 struct mmc_card *card = dev_to_mmc_card(dev); 63 struct mmc_card *card = dev_to_mmc_card(dev);
65 const char *type; 64 const char *type;
66 int i = 0, length = 0; 65 int retval = 0;
67 66
68 switch (card->type) { 67 switch (card->type) {
69 case MMC_TYPE_MMC: 68 case MMC_TYPE_MMC:
@@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
80 } 79 }
81 80
82 if (type) { 81 if (type) {
83 if (add_uevent_var(envp, num_envp, &i, 82 retval = add_uevent_var(env, "MMC_TYPE=%s", type);
84 buf, buf_size, &length, 83 if (retval)
85 "MMC_TYPE=%s", type)) 84 return retval;
86 return -ENOMEM;
87 } 85 }
88 86
89 if (add_uevent_var(envp, num_envp, &i, 87 retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
90 buf, buf_size, &length,
91 "MMC_NAME=%s", mmc_card_name(card)))
92 return -ENOMEM;
93 88
94 envp[i] = NULL; 89 return retval;
95
96 return 0;
97} 90}
98 91
99static int mmc_bus_probe(struct device *dev) 92static 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 @@
3#include <linux/module.h> 3#include <linux/module.h>
4#include "pci.h" 4#include "pci.h"
5 5
6int pci_uevent(struct device *dev, char **envp, int num_envp, 6int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
7 char *buffer, int buffer_size)
8{ 7{
9 struct pci_dev *pdev; 8 struct pci_dev *pdev;
10 int i = 0;
11 int length = 0;
12 9
13 if (!dev) 10 if (!dev)
14 return -ENODEV; 11 return -ENODEV;
@@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp,
17 if (!pdev) 14 if (!pdev)
18 return -ENODEV; 15 return -ENODEV;
19 16
20 if (add_uevent_var(envp, num_envp, &i, 17 if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
21 buffer, buffer_size, &length,
22 "PCI_CLASS=%04X", pdev->class))
23 return -ENOMEM; 18 return -ENOMEM;
24 19
25 if (add_uevent_var(envp, num_envp, &i, 20 if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
26 buffer, buffer_size, &length,
27 "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
28 return -ENOMEM; 21 return -ENOMEM;
29 22
30 if (add_uevent_var(envp, num_envp, &i, 23 if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
31 buffer, buffer_size, &length,
32 "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
33 pdev->subsystem_device)) 24 pdev->subsystem_device))
34 return -ENOMEM; 25 return -ENOMEM;
35 26
36 if (add_uevent_var(envp, num_envp, &i, 27 if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
37 buffer, buffer_size, &length,
38 "PCI_SLOT_NAME=%s", pci_name(pdev)))
39 return -ENOMEM; 28 return -ENOMEM;
40 29
41 if (add_uevent_var(envp, num_envp, &i, 30 if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
42 buffer, buffer_size, &length,
43 "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
44 pdev->vendor, pdev->device, 31 pdev->vendor, pdev->device,
45 pdev->subsystem_vendor, pdev->subsystem_device, 32 pdev->subsystem_vendor, pdev->subsystem_device,
46 (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), 33 (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
47 (u8)(pdev->class))) 34 (u8)(pdev->class)))
48 return -ENOMEM; 35 return -ENOMEM;
49
50 envp[i] = NULL;
51
52 return 0; 36 return 0;
53} 37}
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)
532} 532}
533 533
534#ifndef CONFIG_HOTPLUG 534#ifndef CONFIG_HOTPLUG
535int pci_uevent(struct device *dev, char **envp, int num_envp, 535int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
536 char *buffer, int buffer_size)
537{ 536{
538 return -ENODEV; 537 return -ENODEV;
539} 538}
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 @@
1/* Functions internal to the PCI core code */ 1/* Functions internal to the PCI core code */
2 2
3extern int pci_uevent(struct device *dev, char **envp, int num_envp, 3extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
4 char *buffer, int buffer_size);
5extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); 4extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
6extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); 5extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
7extern void pci_cleanup_rom(struct pci_dev *dev); 6extern 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)
907EXPORT_SYMBOL(pcmcia_insert_card); 907EXPORT_SYMBOL(pcmcia_insert_card);
908 908
909 909
910static int pcmcia_socket_uevent(struct device *dev, char **envp, 910static int pcmcia_socket_uevent(struct device *dev,
911 int num_envp, char *buffer, int buffer_size) 911 struct kobj_uevent_env *env)
912{ 912{
913 struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); 913 struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
914 int i = 0, length = 0;
915 914
916 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 915 if (add_uevent_var(env, "SOCKET_NO=%u", s->sock))
917 &length, "SOCKET_NO=%u", s->sock))
918 return -ENOMEM; 916 return -ENOMEM;
919 917
920 envp[i] = NULL;
921
922 return 0; 918 return 0;
923} 919}
924 920
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) {
1064 1064
1065#ifdef CONFIG_HOTPLUG 1065#ifdef CONFIG_HOTPLUG
1066 1066
1067static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, 1067static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
1068 char *buffer, int buffer_size)
1069{ 1068{
1070 struct pcmcia_device *p_dev; 1069 struct pcmcia_device *p_dev;
1071 int i, length = 0; 1070 int i;
1072 u32 hash[4] = { 0, 0, 0, 0}; 1071 u32 hash[4] = { 0, 0, 0, 0};
1073 1072
1074 if (!dev) 1073 if (!dev)
@@ -1083,23 +1082,13 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
1083 hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); 1082 hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
1084 } 1083 }
1085 1084
1086 i = 0; 1085 if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock))
1087
1088 if (add_uevent_var(envp, num_envp, &i,
1089 buffer, buffer_size, &length,
1090 "SOCKET_NO=%u",
1091 p_dev->socket->sock))
1092 return -ENOMEM; 1086 return -ENOMEM;
1093 1087
1094 if (add_uevent_var(envp, num_envp, &i, 1088 if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
1095 buffer, buffer_size, &length,
1096 "DEVICE_NO=%02X",
1097 p_dev->device_no))
1098 return -ENOMEM; 1089 return -ENOMEM;
1099 1090
1100 if (add_uevent_var(envp, num_envp, &i, 1091 if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
1101 buffer, buffer_size, &length,
1102 "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
1103 "pa%08Xpb%08Xpc%08Xpd%08X", 1092 "pa%08Xpb%08Xpc%08Xpd%08X",
1104 p_dev->has_manf_id ? p_dev->manf_id : 0, 1093 p_dev->has_manf_id ? p_dev->manf_id : 0,
1105 p_dev->has_card_id ? p_dev->card_id : 0, 1094 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,
1112 hash[3])) 1101 hash[3]))
1113 return -ENOMEM; 1102 return -ENOMEM;
1114 1103
1115 envp[i] = NULL;
1116
1117 return 0; 1104 return 0;
1118} 1105}
1119 1106
1120#else 1107#else
1121 1108
1122static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, 1109static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
1123 char *buffer, int buffer_size)
1124{ 1110{
1125 return -ENODEV; 1111 return -ENODEV;
1126} 1112}
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 @@
14 14
15extern int power_supply_create_attrs(struct power_supply *psy); 15extern int power_supply_create_attrs(struct power_supply *psy);
16extern void power_supply_remove_attrs(struct power_supply *psy); 16extern void power_supply_remove_attrs(struct power_supply *psy);
17extern int power_supply_uevent(struct device *dev, char **envp, int num_envp, 17extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env);
18 char *buffer, int buffer_size);
19 18
20#else 19#else
21 20
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)
195 return ret; 195 return ret;
196} 196}
197 197
198int power_supply_uevent(struct device *dev, char **envp, int num_envp, 198int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
199 char *buffer, int buffer_size)
200{ 199{
201 struct power_supply *psy = dev_get_drvdata(dev); 200 struct power_supply *psy = dev_get_drvdata(dev);
202 int i = 0, length = 0, ret = 0, j; 201 int ret = 0, j;
203 char *prop_buf; 202 char *prop_buf;
204 char *attrname; 203 char *attrname;
205 204
@@ -212,8 +211,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
212 211
213 dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name); 212 dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
214 213
215 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 214 ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);
216 &length, "POWER_SUPPLY_NAME=%s", psy->name);
217 if (ret) 215 if (ret)
218 return ret; 216 return ret;
219 217
@@ -243,9 +241,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
243 241
244 dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf); 242 dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
245 243
246 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 244 ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
247 &length, "POWER_SUPPLY_%s=%s",
248 attrname, prop_buf);
249 kfree(attrname); 245 kfree(attrname);
250 if (ret) 246 if (ret)
251 goto out; 247 goto out;
@@ -282,14 +278,11 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
282 278
283 dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); 279 dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
284 280
285 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, 281 ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
286 &length, "POWER_SUPPLY_%s=%s",
287 attrname, prop_buf);
288 kfree(attrname); 282 kfree(attrname);
289 if (ret) 283 if (ret)
290 goto out; 284 goto out;
291 } 285 }
292 envp[i] = NULL;
293 286
294out: 287out:
295 free_page((unsigned long)prop_buf); 288 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)
44 return 0; 44 return 0;
45} 45}
46static int 46static int
47ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, 47ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
48 int buffer_size)
49{ 48{
50 /* TODO */ 49 /* TODO */
51 return 0; 50 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,
78 78
79/* Set up environment variables for ccw device uevent. Return 0 on success, 79/* Set up environment variables for ccw device uevent. Return 0 on success,
80 * non-zero otherwise. */ 80 * non-zero otherwise. */
81static int ccw_uevent(struct device *dev, char **envp, int num_envp, 81static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
82 char *buffer, int buffer_size)
83{ 82{
84 struct ccw_device *cdev = to_ccwdev(dev); 83 struct ccw_device *cdev = to_ccwdev(dev);
85 struct ccw_device_id *id = &(cdev->id); 84 struct ccw_device_id *id = &(cdev->id);
86 int i = 0;
87 int len = 0;
88 int ret; 85 int ret;
89 char modalias_buf[30]; 86 char modalias_buf[30];
90 87
91 /* CU_TYPE= */ 88 /* CU_TYPE= */
92 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 89 ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type);
93 "CU_TYPE=%04X", id->cu_type);
94 if (ret) 90 if (ret)
95 return ret; 91 return ret;
96 92
97 /* CU_MODEL= */ 93 /* CU_MODEL= */
98 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 94 ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model);
99 "CU_MODEL=%02X", id->cu_model);
100 if (ret) 95 if (ret)
101 return ret; 96 return ret;
102 97
103 /* The next two can be zero, that's ok for us */ 98 /* The next two can be zero, that's ok for us */
104 /* DEV_TYPE= */ 99 /* DEV_TYPE= */
105 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 100 ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type);
106 "DEV_TYPE=%04X", id->dev_type);
107 if (ret) 101 if (ret)
108 return ret; 102 return ret;
109 103
110 /* DEV_MODEL= */ 104 /* DEV_MODEL= */
111 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 105 ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model);
112 "DEV_MODEL=%02X", id->dev_model);
113 if (ret) 106 if (ret)
114 return ret; 107 return ret;
115 108
116 /* MODALIAS= */ 109 /* MODALIAS= */
117 snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); 110 snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
118 ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, 111 ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf);
119 "MODALIAS=%s", modalias_buf); 112 return ret;
120 if (ret)
121 return ret;
122 envp[i] = NULL;
123 return 0;
124} 113}
125 114
126struct bus_type ccw_bus_type; 115struct 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)
458 * uevent function for AP devices. It sets up a single environment 458 * uevent function for AP devices. It sets up a single environment
459 * variable DEV_TYPE which contains the hardware device type. 459 * variable DEV_TYPE which contains the hardware device type.
460 */ 460 */
461static int ap_uevent (struct device *dev, char **envp, int num_envp, 461static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
462 char *buffer, int buffer_size)
463{ 462{
464 struct ap_device *ap_dev = to_ap_dev(dev); 463 struct ap_device *ap_dev = to_ap_dev(dev);
465 int retval = 0, length = 0, i = 0; 464 int retval = 0;
466 465
467 if (!ap_dev) 466 if (!ap_dev)
468 return -ENODEV; 467 return -ENODEV;
469 468
470 /* Set up DEV_TYPE environment variable. */ 469 /* Set up DEV_TYPE environment variable. */
471 retval = add_uevent_var(envp, num_envp, &i, 470 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
472 buffer, buffer_size, &length,
473 "DEV_TYPE=%04X", ap_dev->device_type);
474 if (retval) 471 if (retval)
475 return retval; 472 return retval;
476 473
477 /* Add MODALIAS= */ 474 /* Add MODALIAS= */
478 retval = add_uevent_var(envp, num_envp, &i, 475 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
479 buffer, buffer_size, &length,
480 "MODALIAS=ap:t%02X", ap_dev->device_type);
481 476
482 envp[i] = NULL;
483 return retval; 477 return retval;
484} 478}
485 479
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)
277 return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; 277 return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
278} 278}
279 279
280static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, 280static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
281 char *buffer, int buffer_size)
282{ 281{
283 struct scsi_device *sdev = to_scsi_device(dev); 282 struct scsi_device *sdev = to_scsi_device(dev);
284 int i = 0;
285 int length = 0;
286 283
287 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 284 add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
288 "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
289 envp[i] = NULL;
290 return 0; 285 return 0;
291} 286}
292 287
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)
67 return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; 67 return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
68} 68}
69 69
70static int spi_uevent(struct device *dev, char **envp, int num_envp, 70static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
71 char *buffer, int buffer_size)
72{ 71{
73 const struct spi_device *spi = to_spi_device(dev); 72 const struct spi_device *spi = to_spi_device(dev);
74 73
75 envp[0] = buffer; 74 add_uevent_var(env, "MODALIAS=%s", spi->modalias);
76 snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
77 envp[1] = NULL;
78 return 0; 75 return 0;
79} 76}
80 77
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)
576} 576}
577 577
578#ifdef CONFIG_HOTPLUG 578#ifdef CONFIG_HOTPLUG
579static int usb_uevent(struct device *dev, char **envp, int num_envp, 579static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
580 char *buffer, int buffer_size)
581{ 580{
582 struct usb_device *usb_dev; 581 struct usb_device *usb_dev;
583 int i = 0;
584 int length = 0;
585 582
586 if (!dev) 583 if (!dev)
587 return -ENODEV; 584 return -ENODEV;
@@ -610,51 +607,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
610 * all the device descriptors we don't tell them about. Or 607 * all the device descriptors we don't tell them about. Or
611 * act as usermode drivers. 608 * act as usermode drivers.
612 */ 609 */
613 if (add_uevent_var(envp, num_envp, &i, 610 if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
614 buffer, buffer_size, &length,
615 "DEVICE=/proc/bus/usb/%03d/%03d",
616 usb_dev->bus->busnum, usb_dev->devnum)) 611 usb_dev->bus->busnum, usb_dev->devnum))
617 return -ENOMEM; 612 return -ENOMEM;
618#endif 613#endif
619 614
620 /* per-device configurations are common */ 615 /* per-device configurations are common */
621 if (add_uevent_var(envp, num_envp, &i, 616 if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
622 buffer, buffer_size, &length,
623 "PRODUCT=%x/%x/%x",
624 le16_to_cpu(usb_dev->descriptor.idVendor), 617 le16_to_cpu(usb_dev->descriptor.idVendor),
625 le16_to_cpu(usb_dev->descriptor.idProduct), 618 le16_to_cpu(usb_dev->descriptor.idProduct),
626 le16_to_cpu(usb_dev->descriptor.bcdDevice))) 619 le16_to_cpu(usb_dev->descriptor.bcdDevice)))
627 return -ENOMEM; 620 return -ENOMEM;
628 621
629 /* class-based driver binding models */ 622 /* class-based driver binding models */
630 if (add_uevent_var(envp, num_envp, &i, 623 if (add_uevent_var(env, "TYPE=%d/%d/%d",
631 buffer, buffer_size, &length,
632 "TYPE=%d/%d/%d",
633 usb_dev->descriptor.bDeviceClass, 624 usb_dev->descriptor.bDeviceClass,
634 usb_dev->descriptor.bDeviceSubClass, 625 usb_dev->descriptor.bDeviceSubClass,
635 usb_dev->descriptor.bDeviceProtocol)) 626 usb_dev->descriptor.bDeviceProtocol))
636 return -ENOMEM; 627 return -ENOMEM;
637 628
638 if (add_uevent_var(envp, num_envp, &i, 629 if (add_uevent_var(env, "BUSNUM=%03d",
639 buffer, buffer_size, &length,
640 "BUSNUM=%03d",
641 usb_dev->bus->busnum)) 630 usb_dev->bus->busnum))
642 return -ENOMEM; 631 return -ENOMEM;
643 632
644 if (add_uevent_var(envp, num_envp, &i, 633 if (add_uevent_var(env, "DEVNUM=%03d",
645 buffer, buffer_size, &length,
646 "DEVNUM=%03d",
647 usb_dev->devnum)) 634 usb_dev->devnum))
648 return -ENOMEM; 635 return -ENOMEM;
649 636
650 envp[i] = NULL;
651 return 0; 637 return 0;
652} 638}
653 639
654#else 640#else
655 641
656static int usb_uevent(struct device *dev, char **envp, 642static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
657 int num_envp, char *buffer, int buffer_size)
658{ 643{
659 return -ENODEV; 644 return -ENODEV;
660} 645}
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)
1339} 1339}
1340 1340
1341#ifdef CONFIG_HOTPLUG 1341#ifdef CONFIG_HOTPLUG
1342static int usb_if_uevent(struct device *dev, char **envp, int num_envp, 1342static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
1343 char *buffer, int buffer_size)
1344{ 1343{
1345 struct usb_device *usb_dev; 1344 struct usb_device *usb_dev;
1346 struct usb_interface *intf; 1345 struct usb_interface *intf;
1347 struct usb_host_interface *alt; 1346 struct usb_host_interface *alt;
1348 int i = 0;
1349 int length = 0;
1350 1347
1351 if (!dev) 1348 if (!dev)
1352 return -ENODEV; 1349 return -ENODEV;
@@ -1359,39 +1356,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
1359 alt = intf->cur_altsetting; 1356 alt = intf->cur_altsetting;
1360 1357
1361#ifdef CONFIG_USB_DEVICEFS 1358#ifdef CONFIG_USB_DEVICEFS
1362 if (add_uevent_var(envp, num_envp, &i, 1359 if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
1363 buffer, buffer_size, &length,
1364 "DEVICE=/proc/bus/usb/%03d/%03d",
1365 usb_dev->bus->busnum, usb_dev->devnum)) 1360 usb_dev->bus->busnum, usb_dev->devnum))
1366 return -ENOMEM; 1361 return -ENOMEM;
1367#endif 1362#endif
1368 1363
1369 if (add_uevent_var(envp, num_envp, &i, 1364 if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
1370 buffer, buffer_size, &length,
1371 "PRODUCT=%x/%x/%x",
1372 le16_to_cpu(usb_dev->descriptor.idVendor), 1365 le16_to_cpu(usb_dev->descriptor.idVendor),
1373 le16_to_cpu(usb_dev->descriptor.idProduct), 1366 le16_to_cpu(usb_dev->descriptor.idProduct),
1374 le16_to_cpu(usb_dev->descriptor.bcdDevice))) 1367 le16_to_cpu(usb_dev->descriptor.bcdDevice)))
1375 return -ENOMEM; 1368 return -ENOMEM;
1376 1369
1377 if (add_uevent_var(envp, num_envp, &i, 1370 if (add_uevent_var(env, "TYPE=%d/%d/%d",
1378 buffer, buffer_size, &length,
1379 "TYPE=%d/%d/%d",
1380 usb_dev->descriptor.bDeviceClass, 1371 usb_dev->descriptor.bDeviceClass,
1381 usb_dev->descriptor.bDeviceSubClass, 1372 usb_dev->descriptor.bDeviceSubClass,
1382 usb_dev->descriptor.bDeviceProtocol)) 1373 usb_dev->descriptor.bDeviceProtocol))
1383 return -ENOMEM; 1374 return -ENOMEM;
1384 1375
1385 if (add_uevent_var(envp, num_envp, &i, 1376 if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
1386 buffer, buffer_size, &length,
1387 "INTERFACE=%d/%d/%d",
1388 alt->desc.bInterfaceClass, 1377 alt->desc.bInterfaceClass,
1389 alt->desc.bInterfaceSubClass, 1378 alt->desc.bInterfaceSubClass,
1390 alt->desc.bInterfaceProtocol)) 1379 alt->desc.bInterfaceProtocol))
1391 return -ENOMEM; 1380 return -ENOMEM;
1392 1381
1393 if (add_uevent_var(envp, num_envp, &i, 1382 if (add_uevent_var(env,
1394 buffer, buffer_size, &length,
1395 "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", 1383 "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
1396 le16_to_cpu(usb_dev->descriptor.idVendor), 1384 le16_to_cpu(usb_dev->descriptor.idVendor),
1397 le16_to_cpu(usb_dev->descriptor.idProduct), 1385 le16_to_cpu(usb_dev->descriptor.idProduct),
@@ -1404,14 +1392,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
1404 alt->desc.bInterfaceProtocol)) 1392 alt->desc.bInterfaceProtocol))
1405 return -ENOMEM; 1393 return -ENOMEM;
1406 1394
1407 envp[i] = NULL;
1408 return 0; 1395 return 0;
1409} 1396}
1410 1397
1411#else 1398#else
1412 1399
1413static int usb_if_uevent(struct device *dev, char **envp, 1400static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
1414 int num_envp, char *buffer, int buffer_size)
1415{ 1401{
1416 return -ENODEV; 1402 return -ENODEV;
1417} 1403}
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 = {
197 .fops = &w1_default_fops, 197 .fops = &w1_default_fops,
198}; 198};
199 199
200static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); 200static int w1_uevent(struct device *dev, struct kobj_uevent_env *env);
201 201
202static struct bus_type w1_bus_type = { 202static struct bus_type w1_bus_type = {
203 .name = "w1", 203 .name = "w1",
@@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master)
396} 396}
397 397
398#ifdef CONFIG_HOTPLUG 398#ifdef CONFIG_HOTPLUG
399static int w1_uevent(struct device *dev, char **envp, int num_envp, 399static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
400 char *buffer, int buffer_size)
401{ 400{
402 struct w1_master *md = NULL; 401 struct w1_master *md = NULL;
403 struct w1_slave *sl = NULL; 402 struct w1_slave *sl = NULL;
404 char *event_owner, *name; 403 char *event_owner, *name;
405 int err, cur_index=0, cur_len=0; 404 int err;
406 405
407 if (dev->driver == &w1_master_driver) { 406 if (dev->driver == &w1_master_driver) {
408 md = container_of(dev, struct w1_master, dev); 407 md = container_of(dev, struct w1_master, dev);
@@ -423,23 +422,19 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp,
423 if (dev->driver != &w1_slave_driver || !sl) 422 if (dev->driver != &w1_slave_driver || !sl)
424 return 0; 423 return 0;
425 424
426 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, 425 err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family);
427 &cur_len, "W1_FID=%02X", sl->reg_num.family);
428 if (err) 426 if (err)
429 return err; 427 return err;
430 428
431 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, 429 err = add_uevent_var(env, "W1_SLAVE_ID=%024LX",
432 &cur_len, "W1_SLAVE_ID=%024LX", 430 (unsigned long long)sl->reg_num.id);
433 (unsigned long long)sl->reg_num.id);
434 envp[cur_index] = NULL;
435 if (err) 431 if (err)
436 return err; 432 return err;
437 433
438 return 0; 434 return 0;
439}; 435};
440#else 436#else
441static int w1_uevent(struct device *dev, char **envp, int num_envp, 437static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
442 char *buffer, int buffer_size)
443{ 438{
444 return 0; 439 return 0;
445} 440}
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ec2a8a2c737c..93262f2546ad 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -20,7 +20,7 @@ struct of_device
20extern ssize_t of_device_get_modalias(struct of_device *ofdev, 20extern ssize_t of_device_get_modalias(struct of_device *ofdev,
21 char *str, ssize_t len); 21 char *str, ssize_t len);
22extern int of_device_uevent(struct device *dev, 22extern int of_device_uevent(struct device *dev,
23 char **envp, int num_envp, char *buffer, int buffer_size); 23 struct kobj_uevent_env *env);
24 24
25/* This is just here during the transition */ 25/* This is just here during the transition */
26#include <linux/of_device.h> 26#include <linux/of_device.h>
diff --git a/include/linux/device.h b/include/linux/device.h
index 5d97ca6d8655..2e15822fe409 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -66,8 +66,7 @@ struct bus_type {
66 struct driver_attribute * drv_attrs; 66 struct driver_attribute * drv_attrs;
67 67
68 int (*match)(struct device * dev, struct device_driver * drv); 68 int (*match)(struct device * dev, struct device_driver * drv);
69 int (*uevent)(struct device *dev, char **envp, 69 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
70 int num_envp, char *buffer, int buffer_size);
71 int (*probe)(struct device * dev); 70 int (*probe)(struct device * dev);
72 int (*remove)(struct device * dev); 71 int (*remove)(struct device * dev);
73 void (*shutdown)(struct device * dev); 72 void (*shutdown)(struct device * dev);
@@ -187,10 +186,8 @@ struct class {
187 struct class_device_attribute * class_dev_attrs; 186 struct class_device_attribute * class_dev_attrs;
188 struct device_attribute * dev_attrs; 187 struct device_attribute * dev_attrs;
189 188
190 int (*uevent)(struct class_device *dev, char **envp, 189 int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
191 int num_envp, char *buffer, int buffer_size); 190 int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
192 int (*dev_uevent)(struct device *dev, char **envp, int num_envp,
193 char *buffer, int buffer_size);
194 191
195 void (*release)(struct class_device *dev); 192 void (*release)(struct class_device *dev);
196 void (*class_release)(struct class *class); 193 void (*class_release)(struct class *class);
@@ -266,8 +263,7 @@ struct class_device {
266 struct attribute_group ** groups; /* optional groups */ 263 struct attribute_group ** groups; /* optional groups */
267 264
268 void (*release)(struct class_device *dev); 265 void (*release)(struct class_device *dev);
269 int (*uevent)(struct class_device *dev, char **envp, 266 int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
270 int num_envp, char *buffer, int buffer_size);
271 char class_id[BUS_ID_SIZE]; /* unique to this class */ 267 char class_id[BUS_ID_SIZE]; /* unique to this class */
272}; 268};
273 269
@@ -335,8 +331,7 @@ extern void class_device_destroy(struct class *cls, dev_t devt);
335struct device_type { 331struct device_type {
336 const char *name; 332 const char *name;
337 struct attribute_group **groups; 333 struct attribute_group **groups;
338 int (*uevent)(struct device *dev, char **envp, int num_envp, 334 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
339 char *buffer, int buffer_size);
340 void (*release)(struct device *dev); 335 void (*release)(struct device *dev);
341 int (*suspend)(struct device * dev, pm_message_t state); 336 int (*suspend)(struct device * dev, pm_message_t state);
342 int (*resume)(struct device * dev); 337 int (*resume)(struct device * dev);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 949706c33622..626bdd3c3dd9 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -29,6 +29,8 @@
29 29
30#define KOBJ_NAME_LEN 20 30#define KOBJ_NAME_LEN 20
31#define UEVENT_HELPER_PATH_LEN 256 31#define UEVENT_HELPER_PATH_LEN 256
32#define UEVENT_NUM_ENVP 32 /* number of env pointers */
33#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
32 34
33/* path to the userspace helper executed on an event */ 35/* path to the userspace helper executed on an event */
34extern char uevent_helper[]; 36extern char uevent_helper[];
@@ -111,11 +113,18 @@ struct kobj_type {
111 struct attribute ** default_attrs; 113 struct attribute ** default_attrs;
112}; 114};
113 115
116struct kobj_uevent_env {
117 char *envp[UEVENT_NUM_ENVP];
118 int envp_idx;
119 char buf[UEVENT_BUFFER_SIZE];
120 int buflen;
121};
122
114struct kset_uevent_ops { 123struct kset_uevent_ops {
115 int (*filter)(struct kset *kset, struct kobject *kobj); 124 int (*filter)(struct kset *kset, struct kobject *kobj);
116 const char *(*name)(struct kset *kset, struct kobject *kobj); 125 const char *(*name)(struct kset *kset, struct kobject *kobj);
117 int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp, 126 int (*uevent)(struct kset *kset, struct kobject *kobj,
118 int num_envp, char *buffer, int buffer_size); 127 struct kobj_uevent_env *env);
119}; 128};
120 129
121/* 130/*
@@ -275,10 +284,8 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action);
275int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 284int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
276 char *envp[]); 285 char *envp[]);
277 286
278int add_uevent_var(char **envp, int num_envp, int *cur_index, 287int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
279 char *buffer, int buffer_size, int *cur_len, 288 __attribute__((format (printf, 2, 3)));
280 const char *format, ...)
281 __attribute__((format (printf, 7, 8)));
282#else 289#else
283static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) 290static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action)
284{ return 0; } 291{ return 0; }
@@ -287,9 +294,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
287 char *envp[]) 294 char *envp[])
288{ return 0; } 295{ return 0; }
289 296
290static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, 297static inline int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
291 char *buffer, int buffer_size, int *cur_len,
292 const char *format, ...)
293{ return 0; } 298{ return 0; }
294#endif 299#endif
295 300
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index e06a8dcec0f0..7d8aeb301635 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -22,8 +22,6 @@
22#include <linux/kobject.h> 22#include <linux/kobject.h>
23#include <net/sock.h> 23#include <net/sock.h>
24 24
25#define BUFFER_SIZE 2048 /* buffer for the variables */
26#define NUM_ENVP 32 /* number of env pointers */
27 25
28/* the strings here must match the enum in include/linux/kobject.h */ 26/* the strings here must match the enum in include/linux/kobject.h */
29const char *kobject_actions[] = { 27const char *kobject_actions[] = {
@@ -54,31 +52,21 @@ static struct sock *uevent_sock;
54 * corresponding error when it fails. 52 * corresponding error when it fails.
55 */ 53 */
56int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 54int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
57 char *envp_ext[]) 55 char *envp_ext[])
58{ 56{
59 char **envp; 57 struct kobj_uevent_env *env;
60 char *buffer; 58 const char *action_string = kobject_actions[action];
61 char *scratch;
62 const char *action_string;
63 const char *devpath = NULL; 59 const char *devpath = NULL;
64 const char *subsystem; 60 const char *subsystem;
65 struct kobject *top_kobj; 61 struct kobject *top_kobj;
66 struct kset *kset; 62 struct kset *kset;
67 struct kset_uevent_ops *uevent_ops; 63 struct kset_uevent_ops *uevent_ops;
68 u64 seq; 64 u64 seq;
69 char *seq_buff;
70 int i = 0; 65 int i = 0;
71 int retval = 0; 66 int retval = 0;
72 int j;
73 67
74 pr_debug("%s\n", __FUNCTION__); 68 pr_debug("%s\n", __FUNCTION__);
75 69
76 action_string = kobject_actions[action];
77 if (!action_string) {
78 pr_debug("kobject attempted to send uevent without action_string!\n");
79 return -EINVAL;
80 }
81
82 /* search the kset we belong to */ 70 /* search the kset we belong to */
83 top_kobj = kobj; 71 top_kobj = kobj;
84 while (!top_kobj->kset && top_kobj->parent) { 72 while (!top_kobj->kset && top_kobj->parent) {
@@ -92,7 +80,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
92 kset = top_kobj->kset; 80 kset = top_kobj->kset;
93 uevent_ops = kset->uevent_ops; 81 uevent_ops = kset->uevent_ops;
94 82
95 /* skip the event, if the filter returns zero. */ 83 /* skip the event, if the filter returns zero. */
96 if (uevent_ops && uevent_ops->filter) 84 if (uevent_ops && uevent_ops->filter)
97 if (!uevent_ops->filter(kset, kobj)) { 85 if (!uevent_ops->filter(kset, kobj)) {
98 pr_debug("kobject filter function caused the event to drop!\n"); 86 pr_debug("kobject filter function caused the event to drop!\n");
@@ -109,18 +97,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
109 return 0; 97 return 0;
110 } 98 }
111 99
112 /* environment index */ 100 /* environment buffer */
113 envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); 101 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
114 if (!envp) 102 if (!env)
115 return -ENOMEM; 103 return -ENOMEM;
116 104
117 /* environment values */
118 buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
119 if (!buffer) {
120 retval = -ENOMEM;
121 goto exit;
122 }
123
124 /* complete object path */ 105 /* complete object path */
125 devpath = kobject_get_path(kobj, GFP_KERNEL); 106 devpath = kobject_get_path(kobj, GFP_KERNEL);
126 if (!devpath) { 107 if (!devpath) {
@@ -128,29 +109,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
128 goto exit; 109 goto exit;
129 } 110 }
130 111
131 /* event environemnt for helper process only */
132 envp[i++] = "HOME=/";
133 envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
134
135 /* default keys */ 112 /* default keys */
136 scratch = buffer; 113 retval = add_uevent_var(env, "ACTION=%s", action_string);
137 envp [i++] = scratch; 114 if (retval)
138 scratch += sprintf(scratch, "ACTION=%s", action_string) + 1; 115 goto exit;
139 envp [i++] = scratch; 116 retval = add_uevent_var(env, "DEVPATH=%s", devpath);
140 scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; 117 if (retval)
141 envp [i++] = scratch; 118 goto exit;
142 scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; 119 retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
143 for (j = 0; envp_ext && envp_ext[j]; j++) 120 if (retval)
144 envp[i++] = envp_ext[j]; 121 goto exit;
145 /* just reserve the space, overwrite it after kset call has returned */ 122
146 envp[i++] = seq_buff = scratch; 123 /* keys passed in from the caller */
147 scratch += strlen("SEQNUM=18446744073709551616") + 1; 124 if (envp_ext) {
125 for (i = 0; envp_ext[i]; i++) {
126 retval = add_uevent_var(env, envp_ext[i]);
127 if (retval)
128 goto exit;
129 }
130 }
148 131
149 /* let the kset specific function add its stuff */ 132 /* let the kset specific function add its stuff */
150 if (uevent_ops && uevent_ops->uevent) { 133 if (uevent_ops && uevent_ops->uevent) {
151 retval = uevent_ops->uevent(kset, kobj, 134 retval = uevent_ops->uevent(kset, kobj, env);
152 &envp[i], NUM_ENVP - i, scratch,
153 BUFFER_SIZE - (scratch - buffer));
154 if (retval) { 135 if (retval) {
155 pr_debug ("%s - uevent() returned %d\n", 136 pr_debug ("%s - uevent() returned %d\n",
156 __FUNCTION__, retval); 137 __FUNCTION__, retval);
@@ -158,11 +139,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
158 } 139 }
159 } 140 }
160 141
161 /* we will send an event, request a new sequence number */ 142 /* we will send an event, so request a new sequence number */
162 spin_lock(&sequence_lock); 143 spin_lock(&sequence_lock);
163 seq = ++uevent_seqnum; 144 seq = ++uevent_seqnum;
164 spin_unlock(&sequence_lock); 145 spin_unlock(&sequence_lock);
165 sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq); 146 retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
147 if (retval)
148 goto exit;
166 149
167#if defined(CONFIG_NET) 150#if defined(CONFIG_NET)
168 /* send netlink message */ 151 /* send netlink message */
@@ -172,17 +155,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
172 155
173 /* allocate message with the maximum possible size */ 156 /* allocate message with the maximum possible size */
174 len = strlen(action_string) + strlen(devpath) + 2; 157 len = strlen(action_string) + strlen(devpath) + 2;
175 skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL); 158 skb = alloc_skb(len + env->buflen, GFP_KERNEL);
176 if (skb) { 159 if (skb) {
160 char *scratch;
161
177 /* add header */ 162 /* add header */
178 scratch = skb_put(skb, len); 163 scratch = skb_put(skb, len);
179 sprintf(scratch, "%s@%s", action_string, devpath); 164 sprintf(scratch, "%s@%s", action_string, devpath);
180 165
181 /* copy keys to our continuous event payload buffer */ 166 /* copy keys to our continuous event payload buffer */
182 for (i = 2; envp[i]; i++) { 167 for (i = 0; i < env->envp_idx; i++) {
183 len = strlen(envp[i]) + 1; 168 len = strlen(env->envp[i]) + 1;
184 scratch = skb_put(skb, len); 169 scratch = skb_put(skb, len);
185 strcpy(scratch, envp[i]); 170 strcpy(scratch, env->envp[i]);
186 } 171 }
187 172
188 NETLINK_CB(skb).dst_group = 1; 173 NETLINK_CB(skb).dst_group = 1;
@@ -198,13 +183,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
198 argv [0] = uevent_helper; 183 argv [0] = uevent_helper;
199 argv [1] = (char *)subsystem; 184 argv [1] = (char *)subsystem;
200 argv [2] = NULL; 185 argv [2] = NULL;
201 call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC); 186 retval = add_uevent_var(env, "HOME=/");
187 if (retval)
188 goto exit;
189 retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
190 if (retval)
191 goto exit;
192
193 call_usermodehelper (argv[0], argv, env->envp, UMH_WAIT_EXEC);
202 } 194 }
203 195
204exit: 196exit:
205 kfree(devpath); 197 kfree(devpath);
206 kfree(buffer); 198 kfree(env);
207 kfree(envp);
208 return retval; 199 return retval;
209} 200}
210 201
@@ -227,52 +218,38 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action)
227EXPORT_SYMBOL_GPL(kobject_uevent); 218EXPORT_SYMBOL_GPL(kobject_uevent);
228 219
229/** 220/**
230 * add_uevent_var - helper for creating event variables 221 * add_uevent_var - add key value string to the environment buffer
231 * @envp: Pointer to table of environment variables, as passed into 222 * @env: environment buffer structure
232 * uevent() method. 223 * @format: printf format for the key=value pair
233 * @num_envp: Number of environment variable slots available, as
234 * passed into uevent() method.
235 * @cur_index: Pointer to current index into @envp. It should be
236 * initialized to 0 before the first call to add_uevent_var(),
237 * and will be incremented on success.
238 * @buffer: Pointer to buffer for environment variables, as passed
239 * into uevent() method.
240 * @buffer_size: Length of @buffer, as passed into uevent() method.
241 * @cur_len: Pointer to current length of space used in @buffer.
242 * Should be initialized to 0 before the first call to
243 * add_uevent_var(), and will be incremented on success.
244 * @format: Format for creating environment variable (of the form
245 * "XXX=%x") for snprintf().
246 * 224 *
247 * Returns 0 if environment variable was added successfully or -ENOMEM 225 * Returns 0 if environment variable was added successfully or -ENOMEM
248 * if no space was available. 226 * if no space was available.
249 */ 227 */
250int add_uevent_var(char **envp, int num_envp, int *cur_index, 228int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
251 char *buffer, int buffer_size, int *cur_len,
252 const char *format, ...)
253{ 229{
254 va_list args; 230 va_list args;
231 int len;
255 232
256 /* 233 if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
257 * We check against num_envp - 1 to make sure there is at 234 printk(KERN_ERR "add_uevent_var: too many keys\n");
258 * least one slot left after we return, since kobject_uevent() 235 WARN_ON(1);
259 * needs to set the last slot to NULL.
260 */
261 if (*cur_index >= num_envp - 1)
262 return -ENOMEM; 236 return -ENOMEM;
263 237 }
264 envp[*cur_index] = buffer + *cur_len;
265 238
266 va_start(args, format); 239 va_start(args, format);
267 *cur_len += vsnprintf(envp[*cur_index], 240 len = vsnprintf(&env->buf[env->buflen],
268 max(buffer_size - *cur_len, 0), 241 sizeof(env->buf) - env->buflen,
269 format, args) + 1; 242 format, args);
270 va_end(args); 243 va_end(args);
271 244
272 if (*cur_len > buffer_size) 245 if (len >= (sizeof(env->buf) - env->buflen)) {
246 printk(KERN_ERR "add_uevent_var: buffer size too small\n");
247 WARN_ON(1);
273 return -ENOMEM; 248 return -ENOMEM;
249 }
274 250
275 (*cur_index)++; 251 env->envp[env->envp_idx++] = &env->buf[env->buflen];
252 env->buflen += len + 1;
276 return 0; 253 return 0;
277} 254}
278EXPORT_SYMBOL_GPL(add_uevent_var); 255EXPORT_SYMBOL_GPL(add_uevent_var);
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index f094a0879c16..9ef07eda2c43 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -105,10 +105,9 @@ static struct class_device_attribute *atm_attrs[] = {
105 NULL 105 NULL
106}; 106};
107 107
108static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) 108static int atm_uevent(struct class_device *cdev, struct kobj_uevent_env *env)
109{ 109{
110 struct atm_dev *adev; 110 struct atm_dev *adev;
111 int i = 0, len = 0;
112 111
113 if (!cdev) 112 if (!cdev)
114 return -ENODEV; 113 return -ENODEV;
@@ -117,11 +116,9 @@ static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char
117 if (!adev) 116 if (!adev)
118 return -ENODEV; 117 return -ENODEV;
119 118
120 if (add_uevent_var(envp, num_envp, &i, buf, size, &len, 119 if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number))
121 "NAME=%s%d", adev->type, adev->number))
122 return -ENOMEM; 120 return -ENOMEM;
123 121
124 envp[i] = NULL;
125 return 0; 122 return 0;
126} 123}
127 124
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 909a03d6c0e9..6628e457ddc0 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -396,28 +396,22 @@ static struct attribute_group wireless_group = {
396#endif /* CONFIG_SYSFS */ 396#endif /* CONFIG_SYSFS */
397 397
398#ifdef CONFIG_HOTPLUG 398#ifdef CONFIG_HOTPLUG
399static int netdev_uevent(struct device *d, char **envp, 399static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
400 int num_envp, char *buf, int size)
401{ 400{
402 struct net_device *dev = to_net_dev(d); 401 struct net_device *dev = to_net_dev(d);
403 int retval, len = 0, i = 0; 402 int retval;
404 403
405 /* pass interface to uevent. */ 404 /* pass interface to uevent. */
406 retval = add_uevent_var(envp, num_envp, &i, 405 retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
407 buf, size, &len,
408 "INTERFACE=%s", dev->name);
409 if (retval) 406 if (retval)
410 goto exit; 407 goto exit;
411 408
412 /* pass ifindex to uevent. 409 /* pass ifindex to uevent.
413 * ifindex is useful as it won't change (interface name may change) 410 * ifindex is useful as it won't change (interface name may change)
414 * and is what RtNetlink uses natively. */ 411 * and is what RtNetlink uses natively. */
415 retval = add_uevent_var(envp, num_envp, &i, 412 retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex);
416 buf, size, &len,
417 "IFINDEX=%d", dev->ifindex);
418 413
419exit: 414exit:
420 envp[i] = NULL;
421 return retval; 415 return retval;
422} 416}
423#endif 417#endif
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 2d5d2255a27c..29f820e18251 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -53,8 +53,7 @@ static void wiphy_dev_release(struct device *dev)
53} 53}
54 54
55#ifdef CONFIG_HOTPLUG 55#ifdef CONFIG_HOTPLUG
56static int wiphy_uevent(struct device *dev, char **envp, 56static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
57 int num_envp, char *buf, int size)
58{ 57{
59 /* TODO, we probably need stuff here */ 58 /* TODO, we probably need stuff here */
60 return 0; 59 return 0;
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
index 64d163914335..f84f3e505788 100644
--- a/sound/aoa/soundbus/core.c
+++ b/sound/aoa/soundbus/core.c
@@ -56,13 +56,12 @@ static int soundbus_probe(struct device *dev)
56} 56}
57 57
58 58
59static int soundbus_uevent(struct device *dev, char **envp, int num_envp, 59static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env)
60 char *buffer, int buffer_size)
61{ 60{
62 struct soundbus_dev * soundbus_dev; 61 struct soundbus_dev * soundbus_dev;
63 struct of_device * of; 62 struct of_device * of;
64 const char *compat; 63 const char *compat;
65 int retval = 0, i = 0, length = 0; 64 int retval = 0;
66 int cplen, seen = 0; 65 int cplen, seen = 0;
67 66
68 if (!dev) 67 if (!dev)
@@ -75,15 +74,11 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
75 of = &soundbus_dev->ofdev; 74 of = &soundbus_dev->ofdev;
76 75
77 /* stuff we want to pass to /sbin/hotplug */ 76 /* stuff we want to pass to /sbin/hotplug */
78 retval = add_uevent_var(envp, num_envp, &i, 77 retval = add_uevent_var(env, "OF_NAME=%s", of->node->name);
79 buffer, buffer_size, &length,
80 "OF_NAME=%s", of->node->name);
81 if (retval) 78 if (retval)
82 return retval; 79 return retval;
83 80
84 retval = add_uevent_var(envp, num_envp, &i, 81 retval = add_uevent_var(env, "OF_TYPE=%s", of->node->type);
85 buffer, buffer_size, &length,
86 "OF_TYPE=%s", of->node->type);
87 if (retval) 82 if (retval)
88 return retval; 83 return retval;
89 84
@@ -93,27 +88,19 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
93 88
94 compat = of_get_property(of->node, "compatible", &cplen); 89 compat = of_get_property(of->node, "compatible", &cplen);
95 while (compat && cplen > 0) { 90 while (compat && cplen > 0) {
96 int tmp = length; 91 int tmp = env->buflen;
97 retval = add_uevent_var(envp, num_envp, &i, 92 retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
98 buffer, buffer_size, &length,
99 "OF_COMPATIBLE_%d=%s", seen, compat);
100 if (retval) 93 if (retval)
101 return retval; 94 return retval;
102 compat += length - tmp; 95 compat += env->buflen - tmp;
103 cplen -= length - tmp; 96 cplen -= env->buflen - tmp;
104 seen += 1; 97 seen += 1;
105 } 98 }
106 99
107 retval = add_uevent_var(envp, num_envp, &i, 100 retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
108 buffer, buffer_size, &length,
109 "OF_COMPATIBLE_N=%d", seen);
110 if (retval) 101 if (retval)
111 return retval; 102 return retval;
112 retval = add_uevent_var(envp, num_envp, &i, 103 retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias);
113 buffer, buffer_size, &length,
114 "MODALIAS=%s", soundbus_dev->modalias);
115
116 envp[i] = NULL;
117 104
118 return retval; 105 return retval;
119} 106}