diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 108 |
1 files changed, 32 insertions, 76 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index ec86d6fc2360..c1343414d285 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -108,7 +108,7 @@ static void device_release(struct kobject * kobj) | |||
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | static struct kobj_type ktype_device = { | 111 | static struct kobj_type device_ktype = { |
112 | .release = device_release, | 112 | .release = device_release, |
113 | .sysfs_ops = &dev_sysfs_ops, | 113 | .sysfs_ops = &dev_sysfs_ops, |
114 | }; | 114 | }; |
@@ -118,7 +118,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
118 | { | 118 | { |
119 | struct kobj_type *ktype = get_ktype(kobj); | 119 | struct kobj_type *ktype = get_ktype(kobj); |
120 | 120 | ||
121 | if (ktype == &ktype_device) { | 121 | if (ktype == &device_ktype) { |
122 | struct device *dev = to_dev(kobj); | 122 | struct device *dev = to_dev(kobj); |
123 | if (dev->uevent_suppress) | 123 | if (dev->uevent_suppress) |
124 | return 0; | 124 | return 0; |
@@ -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 | ||
144 | static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 144 | static 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,22 +227,18 @@ 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; |
262 | 234 | ||
263 | /* search the kset, the device belongs to */ | 235 | /* search the kset, the device belongs to */ |
264 | top_kobj = &dev->kobj; | 236 | top_kobj = &dev->kobj; |
265 | if (!top_kobj->kset && top_kobj->parent) { | 237 | while (!top_kobj->kset && top_kobj->parent) |
266 | do { | 238 | top_kobj = top_kobj->parent; |
267 | top_kobj = top_kobj->parent; | ||
268 | } while (!top_kobj->kset && top_kobj->parent); | ||
269 | } | ||
270 | if (!top_kobj->kset) | 239 | if (!top_kobj->kset) |
271 | goto out; | 240 | goto out; |
241 | |||
272 | kset = top_kobj->kset; | 242 | kset = top_kobj->kset; |
273 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) | 243 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) |
274 | goto out; | 244 | goto out; |
@@ -278,43 +248,29 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, | |||
278 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) | 248 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) |
279 | goto out; | 249 | goto out; |
280 | 250 | ||
281 | data = (char *)get_zeroed_page(GFP_KERNEL); | 251 | env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); |
282 | if (!data) | 252 | if (!env) |
283 | return -ENOMEM; | 253 | return -ENOMEM; |
284 | 254 | ||
285 | /* let the kset specific function add its keys */ | 255 | /* let the kset specific function add its keys */ |
286 | pos = data; | 256 | 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) | 257 | if (retval) |
292 | goto out; | 258 | goto out; |
293 | 259 | ||
294 | /* copy keys to file */ | 260 | /* copy keys to file */ |
295 | for (i = 0; envp[i]; i++) { | 261 | for (i = 0; i < env->envp_idx; i++) |
296 | pos = &buf[count]; | 262 | count += sprintf(&buf[count], "%s\n", env->envp[i]); |
297 | count += sprintf(pos, "%s\n", envp[i]); | ||
298 | } | ||
299 | out: | 263 | out: |
300 | free_page((unsigned long)data); | 264 | kfree(env); |
301 | return count; | 265 | return count; |
302 | } | 266 | } |
303 | 267 | ||
304 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | 268 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, |
305 | const char *buf, size_t count) | 269 | const char *buf, size_t count) |
306 | { | 270 | { |
307 | size_t len = count; | ||
308 | enum kobject_action action; | 271 | enum kobject_action action; |
309 | 272 | ||
310 | if (len && buf[len-1] == '\n') | 273 | if (kobject_action_type(buf, count, &action) == 0) { |
311 | len--; | ||
312 | |||
313 | for (action = 0; action < KOBJ_MAX; action++) { | ||
314 | if (strncmp(kobject_actions[action], buf, len) != 0) | ||
315 | continue; | ||
316 | if (kobject_actions[action][len] != '\0') | ||
317 | continue; | ||
318 | kobject_uevent(&dev->kobj, action); | 274 | kobject_uevent(&dev->kobj, action); |
319 | goto out; | 275 | goto out; |
320 | } | 276 | } |
@@ -449,7 +405,7 @@ static struct device_attribute devt_attr = | |||
449 | * devices_subsys - structure to be registered with kobject core. | 405 | * devices_subsys - structure to be registered with kobject core. |
450 | */ | 406 | */ |
451 | 407 | ||
452 | decl_subsys(devices, &ktype_device, &device_uevent_ops); | 408 | decl_subsys(devices, &device_ktype, &device_uevent_ops); |
453 | 409 | ||
454 | 410 | ||
455 | /** | 411 | /** |