diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 130 |
1 files changed, 100 insertions, 30 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index b56a0ba31d4a..9630fbdf4e6c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/notifier.h> | 20 | #include <linux/notifier.h> |
21 | #include <linux/genhd.h> | 21 | #include <linux/genhd.h> |
22 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
23 | #include <linux/semaphore.h> | ||
24 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
25 | #include <linux/async.h> | 24 | #include <linux/async.h> |
26 | 25 | ||
@@ -132,9 +131,21 @@ static void device_release(struct kobject *kobj) | |||
132 | kfree(p); | 131 | kfree(p); |
133 | } | 132 | } |
134 | 133 | ||
134 | static const void *device_namespace(struct kobject *kobj) | ||
135 | { | ||
136 | struct device *dev = to_dev(kobj); | ||
137 | const void *ns = NULL; | ||
138 | |||
139 | if (dev->class && dev->class->ns_type) | ||
140 | ns = dev->class->namespace(dev); | ||
141 | |||
142 | return ns; | ||
143 | } | ||
144 | |||
135 | static struct kobj_type device_ktype = { | 145 | static struct kobj_type device_ktype = { |
136 | .release = device_release, | 146 | .release = device_release, |
137 | .sysfs_ops = &dev_sysfs_ops, | 147 | .sysfs_ops = &dev_sysfs_ops, |
148 | .namespace = device_namespace, | ||
138 | }; | 149 | }; |
139 | 150 | ||
140 | 151 | ||
@@ -559,10 +570,10 @@ void device_initialize(struct device *dev) | |||
559 | dev->kobj.kset = devices_kset; | 570 | dev->kobj.kset = devices_kset; |
560 | kobject_init(&dev->kobj, &device_ktype); | 571 | kobject_init(&dev->kobj, &device_ktype); |
561 | INIT_LIST_HEAD(&dev->dma_pools); | 572 | INIT_LIST_HEAD(&dev->dma_pools); |
562 | init_MUTEX(&dev->sem); | 573 | mutex_init(&dev->mutex); |
574 | lockdep_set_novalidate_class(&dev->mutex); | ||
563 | spin_lock_init(&dev->devres_lock); | 575 | spin_lock_init(&dev->devres_lock); |
564 | INIT_LIST_HEAD(&dev->devres_head); | 576 | INIT_LIST_HEAD(&dev->devres_head); |
565 | device_init_wakeup(dev, 0); | ||
566 | device_pm_init(dev); | 577 | device_pm_init(dev); |
567 | set_dev_node(dev, -1); | 578 | set_dev_node(dev, -1); |
568 | } | 579 | } |
@@ -596,11 +607,59 @@ static struct kobject *virtual_device_parent(struct device *dev) | |||
596 | return virtual_dir; | 607 | return virtual_dir; |
597 | } | 608 | } |
598 | 609 | ||
599 | static struct kobject *get_device_parent(struct device *dev, | 610 | struct class_dir { |
600 | struct device *parent) | 611 | struct kobject kobj; |
612 | struct class *class; | ||
613 | }; | ||
614 | |||
615 | #define to_class_dir(obj) container_of(obj, struct class_dir, kobj) | ||
616 | |||
617 | static void class_dir_release(struct kobject *kobj) | ||
618 | { | ||
619 | struct class_dir *dir = to_class_dir(kobj); | ||
620 | kfree(dir); | ||
621 | } | ||
622 | |||
623 | static const | ||
624 | struct kobj_ns_type_operations *class_dir_child_ns_type(struct kobject *kobj) | ||
601 | { | 625 | { |
626 | struct class_dir *dir = to_class_dir(kobj); | ||
627 | return dir->class->ns_type; | ||
628 | } | ||
629 | |||
630 | static struct kobj_type class_dir_ktype = { | ||
631 | .release = class_dir_release, | ||
632 | .sysfs_ops = &kobj_sysfs_ops, | ||
633 | .child_ns_type = class_dir_child_ns_type | ||
634 | }; | ||
635 | |||
636 | static struct kobject * | ||
637 | class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) | ||
638 | { | ||
639 | struct class_dir *dir; | ||
602 | int retval; | 640 | int retval; |
603 | 641 | ||
642 | dir = kzalloc(sizeof(*dir), GFP_KERNEL); | ||
643 | if (!dir) | ||
644 | return NULL; | ||
645 | |||
646 | dir->class = class; | ||
647 | kobject_init(&dir->kobj, &class_dir_ktype); | ||
648 | |||
649 | dir->kobj.kset = &class->p->class_dirs; | ||
650 | |||
651 | retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); | ||
652 | if (retval < 0) { | ||
653 | kobject_put(&dir->kobj); | ||
654 | return NULL; | ||
655 | } | ||
656 | return &dir->kobj; | ||
657 | } | ||
658 | |||
659 | |||
660 | static struct kobject *get_device_parent(struct device *dev, | ||
661 | struct device *parent) | ||
662 | { | ||
604 | if (dev->class) { | 663 | if (dev->class) { |
605 | static DEFINE_MUTEX(gdp_mutex); | 664 | static DEFINE_MUTEX(gdp_mutex); |
606 | struct kobject *kobj = NULL; | 665 | struct kobject *kobj = NULL; |
@@ -635,18 +694,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
635 | } | 694 | } |
636 | 695 | ||
637 | /* or create a new class-directory at the parent device */ | 696 | /* or create a new class-directory at the parent device */ |
638 | k = kobject_create(); | 697 | k = class_dir_create_and_add(dev->class, parent_kobj); |
639 | if (!k) { | ||
640 | mutex_unlock(&gdp_mutex); | ||
641 | return NULL; | ||
642 | } | ||
643 | k->kset = &dev->class->p->class_dirs; | ||
644 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); | ||
645 | if (retval < 0) { | ||
646 | mutex_unlock(&gdp_mutex); | ||
647 | kobject_put(k); | ||
648 | return NULL; | ||
649 | } | ||
650 | /* do not emit an uevent for this simple "glue" directory */ | 698 | /* do not emit an uevent for this simple "glue" directory */ |
651 | mutex_unlock(&gdp_mutex); | 699 | mutex_unlock(&gdp_mutex); |
652 | return k; | 700 | return k; |
@@ -738,7 +786,7 @@ out_device: | |||
738 | out_busid: | 786 | out_busid: |
739 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && | 787 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
740 | device_is_not_partition(dev)) | 788 | device_is_not_partition(dev)) |
741 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, | 789 | sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, |
742 | dev_name(dev)); | 790 | dev_name(dev)); |
743 | #else | 791 | #else |
744 | /* link in the class directory pointing to the device */ | 792 | /* link in the class directory pointing to the device */ |
@@ -756,7 +804,7 @@ out_busid: | |||
756 | return 0; | 804 | return 0; |
757 | 805 | ||
758 | out_busid: | 806 | out_busid: |
759 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev_name(dev)); | 807 | sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev)); |
760 | #endif | 808 | #endif |
761 | 809 | ||
762 | out_subsys: | 810 | out_subsys: |
@@ -784,13 +832,13 @@ static void device_remove_class_symlinks(struct device *dev) | |||
784 | 832 | ||
785 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && | 833 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
786 | device_is_not_partition(dev)) | 834 | device_is_not_partition(dev)) |
787 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, | 835 | sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, |
788 | dev_name(dev)); | 836 | dev_name(dev)); |
789 | #else | 837 | #else |
790 | if (dev->parent && device_is_not_partition(dev)) | 838 | if (dev->parent && device_is_not_partition(dev)) |
791 | sysfs_remove_link(&dev->kobj, "device"); | 839 | sysfs_remove_link(&dev->kobj, "device"); |
792 | 840 | ||
793 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev_name(dev)); | 841 | sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev)); |
794 | #endif | 842 | #endif |
795 | 843 | ||
796 | sysfs_remove_link(&dev->kobj, "subsystem"); | 844 | sysfs_remove_link(&dev->kobj, "subsystem"); |
@@ -1372,7 +1420,7 @@ struct device *__root_device_register(const char *name, struct module *owner) | |||
1372 | return ERR_PTR(err); | 1420 | return ERR_PTR(err); |
1373 | } | 1421 | } |
1374 | 1422 | ||
1375 | #ifdef CONFIG_MODULE /* gotta find a "cleaner" way to do this */ | 1423 | #ifdef CONFIG_MODULES /* gotta find a "cleaner" way to do this */ |
1376 | if (owner) { | 1424 | if (owner) { |
1377 | struct module_kobject *mk = &owner->mkobj; | 1425 | struct module_kobject *mk = &owner->mkobj; |
1378 | 1426 | ||
@@ -1576,6 +1624,14 @@ int device_rename(struct device *dev, char *new_name) | |||
1576 | goto out; | 1624 | goto out; |
1577 | } | 1625 | } |
1578 | 1626 | ||
1627 | #ifndef CONFIG_SYSFS_DEPRECATED | ||
1628 | if (dev->class) { | ||
1629 | error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, | ||
1630 | &dev->kobj, old_device_name, new_name); | ||
1631 | if (error) | ||
1632 | goto out; | ||
1633 | } | ||
1634 | #endif | ||
1579 | error = kobject_rename(&dev->kobj, new_name); | 1635 | error = kobject_rename(&dev->kobj, new_name); |
1580 | if (error) | 1636 | if (error) |
1581 | goto out; | 1637 | goto out; |
@@ -1590,11 +1646,6 @@ int device_rename(struct device *dev, char *new_name) | |||
1590 | new_class_name); | 1646 | new_class_name); |
1591 | } | 1647 | } |
1592 | } | 1648 | } |
1593 | #else | ||
1594 | if (dev->class) { | ||
1595 | error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, | ||
1596 | &dev->kobj, old_device_name, new_name); | ||
1597 | } | ||
1598 | #endif | 1649 | #endif |
1599 | 1650 | ||
1600 | out: | 1651 | out: |
@@ -1735,10 +1786,25 @@ EXPORT_SYMBOL_GPL(device_move); | |||
1735 | */ | 1786 | */ |
1736 | void device_shutdown(void) | 1787 | void device_shutdown(void) |
1737 | { | 1788 | { |
1738 | struct device *dev, *devn; | 1789 | struct device *dev; |
1790 | |||
1791 | spin_lock(&devices_kset->list_lock); | ||
1792 | /* | ||
1793 | * Walk the devices list backward, shutting down each in turn. | ||
1794 | * Beware that device unplug events may also start pulling | ||
1795 | * devices offline, even as the system is shutting down. | ||
1796 | */ | ||
1797 | while (!list_empty(&devices_kset->list)) { | ||
1798 | dev = list_entry(devices_kset->list.prev, struct device, | ||
1799 | kobj.entry); | ||
1800 | get_device(dev); | ||
1801 | /* | ||
1802 | * Make sure the device is off the kset list, in the | ||
1803 | * event that dev->*->shutdown() doesn't remove it. | ||
1804 | */ | ||
1805 | list_del_init(&dev->kobj.entry); | ||
1806 | spin_unlock(&devices_kset->list_lock); | ||
1739 | 1807 | ||
1740 | list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list, | ||
1741 | kobj.entry) { | ||
1742 | if (dev->bus && dev->bus->shutdown) { | 1808 | if (dev->bus && dev->bus->shutdown) { |
1743 | dev_dbg(dev, "shutdown\n"); | 1809 | dev_dbg(dev, "shutdown\n"); |
1744 | dev->bus->shutdown(dev); | 1810 | dev->bus->shutdown(dev); |
@@ -1746,6 +1812,10 @@ void device_shutdown(void) | |||
1746 | dev_dbg(dev, "shutdown\n"); | 1812 | dev_dbg(dev, "shutdown\n"); |
1747 | dev->driver->shutdown(dev); | 1813 | dev->driver->shutdown(dev); |
1748 | } | 1814 | } |
1815 | put_device(dev); | ||
1816 | |||
1817 | spin_lock(&devices_kset->list_lock); | ||
1749 | } | 1818 | } |
1819 | spin_unlock(&devices_kset->list_lock); | ||
1750 | async_synchronize_full(); | 1820 | async_synchronize_full(); |
1751 | } | 1821 | } |