aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r--drivers/base/class.c112
1 files changed, 76 insertions, 36 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index b1ea4df85c7d..9aa127460262 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -91,14 +91,14 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr)
91 sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); 91 sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
92} 92}
93 93
94struct class * class_get(struct class * cls) 94static struct class *class_get(struct class *cls)
95{ 95{
96 if (cls) 96 if (cls)
97 return container_of(subsys_get(&cls->subsys), struct class, subsys); 97 return container_of(subsys_get(&cls->subsys), struct class, subsys);
98 return NULL; 98 return NULL;
99} 99}
100 100
101void class_put(struct class * cls) 101static void class_put(struct class * cls)
102{ 102{
103 if (cls) 103 if (cls)
104 subsys_put(&cls->subsys); 104 subsys_put(&cls->subsys);
@@ -142,6 +142,7 @@ int class_register(struct class * cls)
142 pr_debug("device class '%s': registering\n", cls->name); 142 pr_debug("device class '%s': registering\n", cls->name);
143 143
144 INIT_LIST_HEAD(&cls->children); 144 INIT_LIST_HEAD(&cls->children);
145 INIT_LIST_HEAD(&cls->devices);
145 INIT_LIST_HEAD(&cls->interfaces); 146 INIT_LIST_HEAD(&cls->interfaces);
146 init_MUTEX(&cls->sem); 147 init_MUTEX(&cls->sem);
147 error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); 148 error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
@@ -504,22 +505,21 @@ void class_device_initialize(struct class_device *class_dev)
504 INIT_LIST_HEAD(&class_dev->node); 505 INIT_LIST_HEAD(&class_dev->node);
505} 506}
506 507
507static char *make_class_name(struct class_device *class_dev) 508char *make_class_name(const char *name, struct kobject *kobj)
508{ 509{
509 char *name; 510 char *class_name;
510 int size; 511 int size;
511 512
512 size = strlen(class_dev->class->name) + 513 size = strlen(name) + strlen(kobject_name(kobj)) + 2;
513 strlen(kobject_name(&class_dev->kobj)) + 2;
514 514
515 name = kmalloc(size, GFP_KERNEL); 515 class_name = kmalloc(size, GFP_KERNEL);
516 if (!name) 516 if (!class_name)
517 return ERR_PTR(-ENOMEM); 517 return ERR_PTR(-ENOMEM);
518 518
519 strcpy(name, class_dev->class->name); 519 strcpy(class_name, name);
520 strcat(name, ":"); 520 strcat(class_name, ":");
521 strcat(name, kobject_name(&class_dev->kobj)); 521 strcat(class_name, kobject_name(kobj));
522 return name; 522 return class_name;
523} 523}
524 524
525int class_device_add(struct class_device *class_dev) 525int class_device_add(struct class_device *class_dev)
@@ -535,18 +535,22 @@ int class_device_add(struct class_device *class_dev)
535 return -EINVAL; 535 return -EINVAL;
536 536
537 if (!strlen(class_dev->class_id)) 537 if (!strlen(class_dev->class_id))
538 goto register_done; 538 goto out1;
539 539
540 parent_class = class_get(class_dev->class); 540 parent_class = class_get(class_dev->class);
541 if (!parent_class) 541 if (!parent_class)
542 goto register_done; 542 goto out1;
543
543 parent_class_dev = class_device_get(class_dev->parent); 544 parent_class_dev = class_device_get(class_dev->parent);
544 545
545 pr_debug("CLASS: registering class device: ID = '%s'\n", 546 pr_debug("CLASS: registering class device: ID = '%s'\n",
546 class_dev->class_id); 547 class_dev->class_id);
547 548
548 /* first, register with generic layer. */ 549 /* first, register with generic layer. */
549 kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); 550 error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
551 if (error)
552 goto out2;
553
550 if (parent_class_dev) 554 if (parent_class_dev)
551 class_dev->kobj.parent = &parent_class_dev->kobj; 555 class_dev->kobj.parent = &parent_class_dev->kobj;
552 else 556 else
@@ -554,41 +558,58 @@ int class_device_add(struct class_device *class_dev)
554 558
555 error = kobject_add(&class_dev->kobj); 559 error = kobject_add(&class_dev->kobj);
556 if (error) 560 if (error)
557 goto register_done; 561 goto out2;
558 562
559 /* add the needed attributes to this device */ 563 /* add the needed attributes to this device */
564 sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem");
560 class_dev->uevent_attr.attr.name = "uevent"; 565 class_dev->uevent_attr.attr.name = "uevent";
561 class_dev->uevent_attr.attr.mode = S_IWUSR; 566 class_dev->uevent_attr.attr.mode = S_IWUSR;
562 class_dev->uevent_attr.attr.owner = parent_class->owner; 567 class_dev->uevent_attr.attr.owner = parent_class->owner;
563 class_dev->uevent_attr.store = store_uevent; 568 class_dev->uevent_attr.store = store_uevent;
564 class_device_create_file(class_dev, &class_dev->uevent_attr); 569 error = class_device_create_file(class_dev, &class_dev->uevent_attr);
570 if (error)
571 goto out3;
565 572
566 if (MAJOR(class_dev->devt)) { 573 if (MAJOR(class_dev->devt)) {
567 struct class_device_attribute *attr; 574 struct class_device_attribute *attr;
568 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 575 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
569 if (!attr) { 576 if (!attr) {
570 error = -ENOMEM; 577 error = -ENOMEM;
571 kobject_del(&class_dev->kobj); 578 goto out4;
572 goto register_done;
573 } 579 }
574 attr->attr.name = "dev"; 580 attr->attr.name = "dev";
575 attr->attr.mode = S_IRUGO; 581 attr->attr.mode = S_IRUGO;
576 attr->attr.owner = parent_class->owner; 582 attr->attr.owner = parent_class->owner;
577 attr->show = show_dev; 583 attr->show = show_dev;
578 class_device_create_file(class_dev, attr); 584 error = class_device_create_file(class_dev, attr);
585 if (error) {
586 kfree(attr);
587 goto out4;
588 }
589
579 class_dev->devt_attr = attr; 590 class_dev->devt_attr = attr;
580 } 591 }
581 592
582 class_device_add_attrs(class_dev); 593 error = class_device_add_attrs(class_dev);
594 if (error)
595 goto out5;
596
583 if (class_dev->dev) { 597 if (class_dev->dev) {
584 class_name = make_class_name(class_dev); 598 class_name = make_class_name(class_dev->class->name,
585 sysfs_create_link(&class_dev->kobj, 599 &class_dev->kobj);
586 &class_dev->dev->kobj, "device"); 600 error = sysfs_create_link(&class_dev->kobj,
587 sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, 601 &class_dev->dev->kobj, "device");
588 class_name); 602 if (error)
603 goto out6;
604 error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
605 class_name);
606 if (error)
607 goto out7;
589 } 608 }
590 609
591 class_device_add_groups(class_dev); 610 error = class_device_add_groups(class_dev);
611 if (error)
612 goto out8;
592 613
593 kobject_uevent(&class_dev->kobj, KOBJ_ADD); 614 kobject_uevent(&class_dev->kobj, KOBJ_ADD);
594 615
@@ -601,11 +622,28 @@ int class_device_add(struct class_device *class_dev)
601 } 622 }
602 up(&parent_class->sem); 623 up(&parent_class->sem);
603 624
604 register_done: 625 goto out1;
605 if (error) { 626
606 class_put(parent_class); 627 out8:
628 if (class_dev->dev)
629 sysfs_remove_link(&class_dev->kobj, class_name);
630 out7:
631 if (class_dev->dev)
632 sysfs_remove_link(&class_dev->kobj, "device");
633 out6:
634 class_device_remove_attrs(class_dev);
635 out5:
636 if (class_dev->devt_attr)
637 class_device_remove_file(class_dev, class_dev->devt_attr);
638 out4:
639 class_device_remove_file(class_dev, &class_dev->uevent_attr);
640 out3:
641 kobject_del(&class_dev->kobj);
642 out2:
643 if(parent_class_dev)
607 class_device_put(parent_class_dev); 644 class_device_put(parent_class_dev);
608 } 645 class_put(parent_class);
646 out1:
609 class_device_put(class_dev); 647 class_device_put(class_dev);
610 kfree(class_name); 648 kfree(class_name);
611 return error; 649 return error;
@@ -695,10 +733,12 @@ void class_device_del(struct class_device *class_dev)
695 } 733 }
696 734
697 if (class_dev->dev) { 735 if (class_dev->dev) {
698 class_name = make_class_name(class_dev); 736 class_name = make_class_name(class_dev->class->name,
737 &class_dev->kobj);
699 sysfs_remove_link(&class_dev->kobj, "device"); 738 sysfs_remove_link(&class_dev->kobj, "device");
700 sysfs_remove_link(&class_dev->dev->kobj, class_name); 739 sysfs_remove_link(&class_dev->dev->kobj, class_name);
701 } 740 }
741 sysfs_remove_link(&class_dev->kobj, "subsystem");
702 class_device_remove_file(class_dev, &class_dev->uevent_attr); 742 class_device_remove_file(class_dev, &class_dev->uevent_attr);
703 if (class_dev->devt_attr) 743 if (class_dev->devt_attr)
704 class_device_remove_file(class_dev, class_dev->devt_attr); 744 class_device_remove_file(class_dev, class_dev->devt_attr);
@@ -760,14 +800,16 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
760 new_name); 800 new_name);
761 801
762 if (class_dev->dev) 802 if (class_dev->dev)
763 old_class_name = make_class_name(class_dev); 803 old_class_name = make_class_name(class_dev->class->name,
804 &class_dev->kobj);
764 805
765 strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); 806 strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
766 807
767 error = kobject_rename(&class_dev->kobj, new_name); 808 error = kobject_rename(&class_dev->kobj, new_name);
768 809
769 if (class_dev->dev) { 810 if (class_dev->dev) {
770 new_class_name = make_class_name(class_dev); 811 new_class_name = make_class_name(class_dev->class->name,
812 &class_dev->kobj);
771 sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, 813 sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
772 new_class_name); 814 new_class_name);
773 sysfs_remove_link(&class_dev->dev->kobj, old_class_name); 815 sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
@@ -858,8 +900,6 @@ EXPORT_SYMBOL_GPL(class_create_file);
858EXPORT_SYMBOL_GPL(class_remove_file); 900EXPORT_SYMBOL_GPL(class_remove_file);
859EXPORT_SYMBOL_GPL(class_register); 901EXPORT_SYMBOL_GPL(class_register);
860EXPORT_SYMBOL_GPL(class_unregister); 902EXPORT_SYMBOL_GPL(class_unregister);
861EXPORT_SYMBOL_GPL(class_get);
862EXPORT_SYMBOL_GPL(class_put);
863EXPORT_SYMBOL_GPL(class_create); 903EXPORT_SYMBOL_GPL(class_create);
864EXPORT_SYMBOL_GPL(class_destroy); 904EXPORT_SYMBOL_GPL(class_destroy);
865 905