diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2007-08-14 09:15:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:51:01 -0400 |
commit | 7eff2e7a8b65c25920207324e56611150eb1cd9a (patch) | |
tree | 02a0eeba9d25d996233e30c18f258dfae0ae2139 /arch/powerpc | |
parent | 8380770c842faef3001e44662953d64ad9a93663 (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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/of_device.c | 37 | ||||
-rw-r--r-- | arch/powerpc/kernel/vio.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/system-bus.c | 9 |
3 files changed, 16 insertions, 46 deletions
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 | ||
60 | int of_device_uevent(struct device *dev, | 60 | int 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 | ||
320 | static int vio_hotplug(struct device *dev, char **envp, int num_envp, | 320 | static 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 | ||
440 | static int ps3_system_bus_uevent(struct device *_dev, char **envp, | 440 | static 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 | ||