diff options
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r-- | drivers/base/class.c | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c index df7fdabd0730..b1ea4df85c7d 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -456,6 +456,35 @@ static void class_device_remove_attrs(struct class_device * cd) | |||
456 | } | 456 | } |
457 | } | 457 | } |
458 | 458 | ||
459 | static int class_device_add_groups(struct class_device * cd) | ||
460 | { | ||
461 | int i; | ||
462 | int error = 0; | ||
463 | |||
464 | if (cd->groups) { | ||
465 | for (i = 0; cd->groups[i]; i++) { | ||
466 | error = sysfs_create_group(&cd->kobj, cd->groups[i]); | ||
467 | if (error) { | ||
468 | while (--i >= 0) | ||
469 | sysfs_remove_group(&cd->kobj, cd->groups[i]); | ||
470 | goto out; | ||
471 | } | ||
472 | } | ||
473 | } | ||
474 | out: | ||
475 | return error; | ||
476 | } | ||
477 | |||
478 | static void class_device_remove_groups(struct class_device * cd) | ||
479 | { | ||
480 | int i; | ||
481 | if (cd->groups) { | ||
482 | for (i = 0; cd->groups[i]; i++) { | ||
483 | sysfs_remove_group(&cd->kobj, cd->groups[i]); | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | |||
459 | static ssize_t show_dev(struct class_device *class_dev, char *buf) | 488 | static ssize_t show_dev(struct class_device *class_dev, char *buf) |
460 | { | 489 | { |
461 | return print_dev_t(buf, class_dev->devt); | 490 | return print_dev_t(buf, class_dev->devt); |
@@ -559,17 +588,18 @@ int class_device_add(struct class_device *class_dev) | |||
559 | class_name); | 588 | class_name); |
560 | } | 589 | } |
561 | 590 | ||
591 | class_device_add_groups(class_dev); | ||
592 | |||
562 | kobject_uevent(&class_dev->kobj, KOBJ_ADD); | 593 | kobject_uevent(&class_dev->kobj, KOBJ_ADD); |
563 | 594 | ||
564 | /* notify any interfaces this device is now here */ | 595 | /* notify any interfaces this device is now here */ |
565 | if (parent_class) { | 596 | down(&parent_class->sem); |
566 | down(&parent_class->sem); | 597 | list_add_tail(&class_dev->node, &parent_class->children); |
567 | list_add_tail(&class_dev->node, &parent_class->children); | 598 | list_for_each_entry(class_intf, &parent_class->interfaces, node) { |
568 | list_for_each_entry(class_intf, &parent_class->interfaces, node) | 599 | if (class_intf->add) |
569 | if (class_intf->add) | 600 | class_intf->add(class_dev, class_intf); |
570 | class_intf->add(class_dev, class_intf); | ||
571 | up(&parent_class->sem); | ||
572 | } | 601 | } |
602 | up(&parent_class->sem); | ||
573 | 603 | ||
574 | register_done: | 604 | register_done: |
575 | if (error) { | 605 | if (error) { |
@@ -673,6 +703,7 @@ void class_device_del(struct class_device *class_dev) | |||
673 | if (class_dev->devt_attr) | 703 | if (class_dev->devt_attr) |
674 | class_device_remove_file(class_dev, class_dev->devt_attr); | 704 | class_device_remove_file(class_dev, class_dev->devt_attr); |
675 | class_device_remove_attrs(class_dev); | 705 | class_device_remove_attrs(class_dev); |
706 | class_device_remove_groups(class_dev); | ||
676 | 707 | ||
677 | kobject_uevent(&class_dev->kobj, KOBJ_REMOVE); | 708 | kobject_uevent(&class_dev->kobj, KOBJ_REMOVE); |
678 | kobject_del(&class_dev->kobj); | 709 | kobject_del(&class_dev->kobj); |