aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2007-12-18 19:40:42 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-01-24 23:40:39 -0500
commit0f4dafc0563c6c49e17fe14b3f5f356e4c4b8806 (patch)
treef4ded2831853cb6ea328d15d72871db6f8c22610 /drivers/base
parent12e339ac6e31a34fe42396aec8fb1c0b43caf61e (diff)
Kobject: auto-cleanup on final unref
We save the current state in the object itself, so we can do proper cleanup when the last reference is dropped. If the initial reference is dropped, the object will be removed from sysfs if needed, if an "add" event was sent, "remove" will be send, and the allocated resources are released. This allows us to clean up some driver core usage as well as allowing us to do other such changes to the rest of the kernel. Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/core.c32
1 files changed, 7 insertions, 25 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 675a719dcdd2..d5d542db96fd 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -576,8 +576,8 @@ static struct kobject *get_device_parent(struct device *dev,
576 576
577 /* 577 /*
578 * If we have no parent, we live in "virtual". 578 * If we have no parent, we live in "virtual".
579 * Class-devices with a bus-device as parent, live 579 * Class-devices with a non class-device as parent, live
580 * in a class-directory to prevent namespace collisions. 580 * in a "glue" directory to prevent namespace collisions.
581 */ 581 */
582 if (parent == NULL) 582 if (parent == NULL)
583 parent_kobj = virtual_device_parent(dev); 583 parent_kobj = virtual_device_parent(dev);
@@ -607,8 +607,7 @@ static struct kobject *get_device_parent(struct device *dev,
607 kobject_put(k); 607 kobject_put(k);
608 return NULL; 608 return NULL;
609 } 609 }
610 /* Do not emit a uevent, as it's not needed for this 610 /* do not emit an uevent for this simple "glue" directory */
611 * "class glue" directory. */
612 return k; 611 return k;
613 } 612 }
614 613
@@ -619,30 +618,13 @@ static struct kobject *get_device_parent(struct device *dev,
619 618
620static void cleanup_device_parent(struct device *dev) 619static void cleanup_device_parent(struct device *dev)
621{ 620{
622 struct device *d; 621 struct kobject *glue_dir = dev->kobj.parent;
623 int other = 0;
624 622
625 if (!dev->class) 623 /* see if we live in a "glue" directory */
626 return; 624 if (!dev->class || glue_dir->kset != &dev->class->class_dirs)
627
628 /* see if we live in a parent class directory */
629 if (dev->kobj.parent->kset != &dev->class->class_dirs)
630 return; 625 return;
631 626
632 /* if we are the last child of our class, delete the directory */ 627 kobject_put(glue_dir);
633 down(&dev->class->sem);
634 list_for_each_entry(d, &dev->class->devices, node) {
635 if (d == dev)
636 continue;
637 if (d->kobj.parent == dev->kobj.parent) {
638 other = 1;
639 break;
640 }
641 }
642 if (!other)
643 kobject_del(dev->kobj.parent);
644 kobject_put(dev->kobj.parent);
645 up(&dev->class->sem);
646} 628}
647#endif 629#endif
648 630