diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2007-12-18 19:40:42 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-01-24 23:40:39 -0500 |
commit | 0f4dafc0563c6c49e17fe14b3f5f356e4c4b8806 (patch) | |
tree | f4ded2831853cb6ea328d15d72871db6f8c22610 /drivers/base | |
parent | 12e339ac6e31a34fe42396aec8fb1c0b43caf61e (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.c | 32 |
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 | ||
620 | static void cleanup_device_parent(struct device *dev) | 619 | static 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 | ||