diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-03-10 01:37:34 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 13:57:28 -0400 |
commit | 621a1672f7377e08a942f205d6742d8af1292aab (patch) | |
tree | 9249308b3df0675f713058e3f5ac0442ce2a5e1e | |
parent | b8c5cec23d5c33b767a1cddebd4f8813a9563e3c (diff) |
driver core: Use attribute groups in struct device_type
Driver core: use attribute groups in struct device_type
Attribute groups are more flexible than attribute lists
(an attribute list can be represented by anonymous group)
so switch struct device_type to use them.
Also rework attribute creation for devices so that they all
cleaned up properly in case of errors.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/core.c | 115 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
2 files changed, 70 insertions, 47 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 9ea12d9b48a6..bb2cc37a4d43 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -246,64 +246,95 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | |||
246 | return count; | 246 | return count; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int device_add_groups(struct device *dev) | 249 | static int device_add_attributes(struct device *dev, |
250 | struct device_attribute *attrs) | ||
251 | { | ||
252 | int error = 0; | ||
253 | int i; | ||
254 | |||
255 | if (attrs) { | ||
256 | for (i = 0; attr_name(attrs[i]); i++) { | ||
257 | error = device_create_file(dev, &attrs[i]); | ||
258 | if (error) | ||
259 | break; | ||
260 | } | ||
261 | if (error) | ||
262 | while (--i >= 0) | ||
263 | device_remove_file(dev, &attrs[i]); | ||
264 | } | ||
265 | return error; | ||
266 | } | ||
267 | |||
268 | static void device_remove_attributes(struct device *dev, | ||
269 | struct device_attribute *attrs) | ||
250 | { | 270 | { |
251 | int i; | 271 | int i; |
272 | |||
273 | if (attrs) | ||
274 | for (i = 0; attr_name(attrs[i]); i++) | ||
275 | device_remove_file(dev, &attrs[i]); | ||
276 | } | ||
277 | |||
278 | static int device_add_groups(struct device *dev, | ||
279 | struct attribute_group **groups) | ||
280 | { | ||
252 | int error = 0; | 281 | int error = 0; |
282 | int i; | ||
253 | 283 | ||
254 | if (dev->groups) { | 284 | if (groups) { |
255 | for (i = 0; dev->groups[i]; i++) { | 285 | for (i = 0; groups[i]; i++) { |
256 | error = sysfs_create_group(&dev->kobj, dev->groups[i]); | 286 | error = sysfs_create_group(&dev->kobj, groups[i]); |
257 | if (error) { | 287 | if (error) { |
258 | while (--i >= 0) | 288 | while (--i >= 0) |
259 | sysfs_remove_group(&dev->kobj, dev->groups[i]); | 289 | sysfs_remove_group(&dev->kobj, groups[i]); |
260 | goto out; | 290 | break; |
261 | } | 291 | } |
262 | } | 292 | } |
263 | } | 293 | } |
264 | out: | ||
265 | return error; | 294 | return error; |
266 | } | 295 | } |
267 | 296 | ||
268 | static void device_remove_groups(struct device *dev) | 297 | static void device_remove_groups(struct device *dev, |
298 | struct attribute_group **groups) | ||
269 | { | 299 | { |
270 | int i; | 300 | int i; |
271 | if (dev->groups) { | 301 | |
272 | for (i = 0; dev->groups[i]; i++) { | 302 | if (groups) |
273 | sysfs_remove_group(&dev->kobj, dev->groups[i]); | 303 | for (i = 0; groups[i]; i++) |
274 | } | 304 | sysfs_remove_group(&dev->kobj, groups[i]); |
275 | } | ||
276 | } | 305 | } |
277 | 306 | ||
278 | static int device_add_attrs(struct device *dev) | 307 | static int device_add_attrs(struct device *dev) |
279 | { | 308 | { |
280 | struct class *class = dev->class; | 309 | struct class *class = dev->class; |
281 | struct device_type *type = dev->type; | 310 | struct device_type *type = dev->type; |
282 | int error = 0; | 311 | int error; |
283 | int i; | ||
284 | 312 | ||
285 | if (class && class->dev_attrs) { | 313 | if (class) { |
286 | for (i = 0; attr_name(class->dev_attrs[i]); i++) { | 314 | error = device_add_attributes(dev, class->dev_attrs); |
287 | error = device_create_file(dev, &class->dev_attrs[i]); | ||
288 | if (error) | ||
289 | break; | ||
290 | } | ||
291 | if (error) | 315 | if (error) |
292 | while (--i >= 0) | 316 | return error; |
293 | device_remove_file(dev, &class->dev_attrs[i]); | ||
294 | } | 317 | } |
295 | 318 | ||
296 | if (type && type->attrs) { | 319 | if (type) { |
297 | for (i = 0; attr_name(type->attrs[i]); i++) { | 320 | error = device_add_groups(dev, type->groups); |
298 | error = device_create_file(dev, &type->attrs[i]); | ||
299 | if (error) | ||
300 | break; | ||
301 | } | ||
302 | if (error) | 321 | if (error) |
303 | while (--i >= 0) | 322 | goto err_remove_class_attrs; |
304 | device_remove_file(dev, &type->attrs[i]); | ||
305 | } | 323 | } |
306 | 324 | ||
325 | error = device_add_groups(dev, dev->groups); | ||
326 | if (error) | ||
327 | goto err_remove_type_groups; | ||
328 | |||
329 | return 0; | ||
330 | |||
331 | err_remove_type_groups: | ||
332 | if (type) | ||
333 | device_remove_groups(dev, type->groups); | ||
334 | err_remove_class_attrs: | ||
335 | if (class) | ||
336 | device_remove_attributes(dev, class->dev_attrs); | ||
337 | |||
307 | return error; | 338 | return error; |
308 | } | 339 | } |
309 | 340 | ||
@@ -311,17 +342,14 @@ static void device_remove_attrs(struct device *dev) | |||
311 | { | 342 | { |
312 | struct class *class = dev->class; | 343 | struct class *class = dev->class; |
313 | struct device_type *type = dev->type; | 344 | struct device_type *type = dev->type; |
314 | int i; | ||
315 | 345 | ||
316 | if (class && class->dev_attrs) { | 346 | device_remove_groups(dev, dev->groups); |
317 | for (i = 0; attr_name(class->dev_attrs[i]); i++) | ||
318 | device_remove_file(dev, &class->dev_attrs[i]); | ||
319 | } | ||
320 | 347 | ||
321 | if (type && type->attrs) { | 348 | if (type) |
322 | for (i = 0; attr_name(type->attrs[i]); i++) | 349 | device_remove_groups(dev, type->groups); |
323 | device_remove_file(dev, &type->attrs[i]); | 350 | |
324 | } | 351 | if (class) |
352 | device_remove_attributes(dev, class->dev_attrs); | ||
325 | } | 353 | } |
326 | 354 | ||
327 | 355 | ||
@@ -638,8 +666,6 @@ int device_add(struct device *dev) | |||
638 | 666 | ||
639 | if ((error = device_add_attrs(dev))) | 667 | if ((error = device_add_attrs(dev))) |
640 | goto AttrsError; | 668 | goto AttrsError; |
641 | if ((error = device_add_groups(dev))) | ||
642 | goto GroupError; | ||
643 | if ((error = device_pm_add(dev))) | 669 | if ((error = device_pm_add(dev))) |
644 | goto PMError; | 670 | goto PMError; |
645 | if ((error = bus_add_device(dev))) | 671 | if ((error = bus_add_device(dev))) |
@@ -663,7 +689,7 @@ int device_add(struct device *dev) | |||
663 | up(&dev->class->sem); | 689 | up(&dev->class->sem); |
664 | } | 690 | } |
665 | Done: | 691 | Done: |
666 | kfree(class_name); | 692 | kfree(class_name); |
667 | put_device(dev); | 693 | put_device(dev); |
668 | return error; | 694 | return error; |
669 | AttachError: | 695 | AttachError: |
@@ -674,8 +700,6 @@ int device_add(struct device *dev) | |||
674 | if (dev->bus) | 700 | if (dev->bus) |
675 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | 701 | blocking_notifier_call_chain(&dev->bus->bus_notifier, |
676 | BUS_NOTIFY_DEL_DEVICE, dev); | 702 | BUS_NOTIFY_DEL_DEVICE, dev); |
677 | device_remove_groups(dev); | ||
678 | GroupError: | ||
679 | device_remove_attrs(dev); | 703 | device_remove_attrs(dev); |
680 | AttrsError: | 704 | AttrsError: |
681 | if (dev->devt_attr) { | 705 | if (dev->devt_attr) { |
@@ -838,7 +862,6 @@ void device_del(struct device * dev) | |||
838 | } | 862 | } |
839 | } | 863 | } |
840 | device_remove_file(dev, &dev->uevent_attr); | 864 | device_remove_file(dev, &dev->uevent_attr); |
841 | device_remove_groups(dev); | ||
842 | device_remove_attrs(dev); | 865 | device_remove_attrs(dev); |
843 | bus_remove_device(dev); | 866 | bus_remove_device(dev); |
844 | 867 | ||
diff --git a/include/linux/device.h b/include/linux/device.h index 9d54fe13eb2e..3b64fdecd041 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -332,7 +332,7 @@ extern struct class_device *class_device_create(struct class *cls, | |||
332 | extern void class_device_destroy(struct class *cls, dev_t devt); | 332 | extern void class_device_destroy(struct class *cls, dev_t devt); |
333 | 333 | ||
334 | struct device_type { | 334 | struct device_type { |
335 | struct device_attribute *attrs; | 335 | struct attribute_group **groups; |
336 | int (*uevent)(struct device *dev, char **envp, int num_envp, | 336 | int (*uevent)(struct device *dev, char **envp, int num_envp, |
337 | char *buffer, int buffer_size); | 337 | char *buffer, int buffer_size); |
338 | void (*release)(struct device *dev); | 338 | void (*release)(struct device *dev); |