aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c71
1 files changed, 44 insertions, 27 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 346be8b78b24..f338037a4f3d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -85,14 +85,13 @@ const char *dev_driver_string(const struct device *dev)
85} 85}
86EXPORT_SYMBOL(dev_driver_string); 86EXPORT_SYMBOL(dev_driver_string);
87 87
88#define to_dev(obj) container_of(obj, struct device, kobj)
89#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) 88#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
90 89
91static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, 90static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
92 char *buf) 91 char *buf)
93{ 92{
94 struct device_attribute *dev_attr = to_dev_attr(attr); 93 struct device_attribute *dev_attr = to_dev_attr(attr);
95 struct device *dev = to_dev(kobj); 94 struct device *dev = kobj_to_dev(kobj);
96 ssize_t ret = -EIO; 95 ssize_t ret = -EIO;
97 96
98 if (dev_attr->show) 97 if (dev_attr->show)
@@ -108,7 +107,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
108 const char *buf, size_t count) 107 const char *buf, size_t count)
109{ 108{
110 struct device_attribute *dev_attr = to_dev_attr(attr); 109 struct device_attribute *dev_attr = to_dev_attr(attr);
111 struct device *dev = to_dev(kobj); 110 struct device *dev = kobj_to_dev(kobj);
112 ssize_t ret = -EIO; 111 ssize_t ret = -EIO;
113 112
114 if (dev_attr->store) 113 if (dev_attr->store)
@@ -182,7 +181,7 @@ EXPORT_SYMBOL_GPL(device_show_int);
182 */ 181 */
183static void device_release(struct kobject *kobj) 182static void device_release(struct kobject *kobj)
184{ 183{
185 struct device *dev = to_dev(kobj); 184 struct device *dev = kobj_to_dev(kobj);
186 struct device_private *p = dev->p; 185 struct device_private *p = dev->p;
187 186
188 if (dev->release) 187 if (dev->release)
@@ -200,7 +199,7 @@ static void device_release(struct kobject *kobj)
200 199
201static const void *device_namespace(struct kobject *kobj) 200static const void *device_namespace(struct kobject *kobj)
202{ 201{
203 struct device *dev = to_dev(kobj); 202 struct device *dev = kobj_to_dev(kobj);
204 const void *ns = NULL; 203 const void *ns = NULL;
205 204
206 if (dev->class && dev->class->ns_type) 205 if (dev->class && dev->class->ns_type)
@@ -221,7 +220,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
221 struct kobj_type *ktype = get_ktype(kobj); 220 struct kobj_type *ktype = get_ktype(kobj);
222 221
223 if (ktype == &device_ktype) { 222 if (ktype == &device_ktype) {
224 struct device *dev = to_dev(kobj); 223 struct device *dev = kobj_to_dev(kobj);
225 if (dev->bus) 224 if (dev->bus)
226 return 1; 225 return 1;
227 if (dev->class) 226 if (dev->class)
@@ -232,7 +231,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
232 231
233static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) 232static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
234{ 233{
235 struct device *dev = to_dev(kobj); 234 struct device *dev = kobj_to_dev(kobj);
236 235
237 if (dev->bus) 236 if (dev->bus)
238 return dev->bus->name; 237 return dev->bus->name;
@@ -244,7 +243,7 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
244static int dev_uevent(struct kset *kset, struct kobject *kobj, 243static int dev_uevent(struct kset *kset, struct kobject *kobj,
245 struct kobj_uevent_env *env) 244 struct kobj_uevent_env *env)
246{ 245{
247 struct device *dev = to_dev(kobj); 246 struct device *dev = kobj_to_dev(kobj);
248 int retval = 0; 247 int retval = 0;
249 248
250 /* add device node properties if present */ 249 /* add device node properties if present */
@@ -1132,7 +1131,7 @@ int device_register(struct device *dev)
1132 */ 1131 */
1133struct device *get_device(struct device *dev) 1132struct device *get_device(struct device *dev)
1134{ 1133{
1135 return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; 1134 return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
1136} 1135}
1137 1136
1138/** 1137/**
@@ -1754,25 +1753,25 @@ int device_move(struct device *dev, struct device *new_parent,
1754 set_dev_node(dev, dev_to_node(new_parent)); 1753 set_dev_node(dev, dev_to_node(new_parent));
1755 } 1754 }
1756 1755
1757 if (!dev->class) 1756 if (dev->class) {
1758 goto out_put; 1757 error = device_move_class_links(dev, old_parent, new_parent);
1759 error = device_move_class_links(dev, old_parent, new_parent); 1758 if (error) {
1760 if (error) { 1759 /* We ignore errors on cleanup since we're hosed anyway... */
1761 /* We ignore errors on cleanup since we're hosed anyway... */ 1760 device_move_class_links(dev, new_parent, old_parent);
1762 device_move_class_links(dev, new_parent, old_parent); 1761 if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
1763 if (!kobject_move(&dev->kobj, &old_parent->kobj)) { 1762 if (new_parent)
1764 if (new_parent) 1763 klist_remove(&dev->p->knode_parent);
1765 klist_remove(&dev->p->knode_parent); 1764 dev->parent = old_parent;
1766 dev->parent = old_parent; 1765 if (old_parent) {
1767 if (old_parent) { 1766 klist_add_tail(&dev->p->knode_parent,
1768 klist_add_tail(&dev->p->knode_parent, 1767 &old_parent->p->klist_children);
1769 &old_parent->p->klist_children); 1768 set_dev_node(dev, dev_to_node(old_parent));
1770 set_dev_node(dev, dev_to_node(old_parent)); 1769 }
1771 } 1770 }
1771 cleanup_glue_dir(dev, new_parent_kobj);
1772 put_device(new_parent);
1773 goto out;
1772 } 1774 }
1773 cleanup_glue_dir(dev, new_parent_kobj);
1774 put_device(new_parent);
1775 goto out;
1776 } 1775 }
1777 switch (dpm_order) { 1776 switch (dpm_order) {
1778 case DPM_ORDER_NONE: 1777 case DPM_ORDER_NONE:
@@ -1787,7 +1786,7 @@ int device_move(struct device *dev, struct device *new_parent,
1787 device_pm_move_last(dev); 1786 device_pm_move_last(dev);
1788 break; 1787 break;
1789 } 1788 }
1790out_put: 1789
1791 put_device(old_parent); 1790 put_device(old_parent);
1792out: 1791out:
1793 device_pm_unlock(); 1792 device_pm_unlock();
@@ -1812,6 +1811,13 @@ void device_shutdown(void)
1812 while (!list_empty(&devices_kset->list)) { 1811 while (!list_empty(&devices_kset->list)) {
1813 dev = list_entry(devices_kset->list.prev, struct device, 1812 dev = list_entry(devices_kset->list.prev, struct device,
1814 kobj.entry); 1813 kobj.entry);
1814
1815 /*
1816 * hold reference count of device's parent to
1817 * prevent it from being freed because parent's
1818 * lock is to be held
1819 */
1820 get_device(dev->parent);
1815 get_device(dev); 1821 get_device(dev);
1816 /* 1822 /*
1817 * Make sure the device is off the kset list, in the 1823 * Make sure the device is off the kset list, in the
@@ -1820,6 +1826,11 @@ void device_shutdown(void)
1820 list_del_init(&dev->kobj.entry); 1826 list_del_init(&dev->kobj.entry);
1821 spin_unlock(&devices_kset->list_lock); 1827 spin_unlock(&devices_kset->list_lock);
1822 1828
1829 /* hold lock to avoid race with probe/release */
1830 if (dev->parent)
1831 device_lock(dev->parent);
1832 device_lock(dev);
1833
1823 /* Don't allow any more runtime suspends */ 1834 /* Don't allow any more runtime suspends */
1824 pm_runtime_get_noresume(dev); 1835 pm_runtime_get_noresume(dev);
1825 pm_runtime_barrier(dev); 1836 pm_runtime_barrier(dev);
@@ -1831,7 +1842,13 @@ void device_shutdown(void)
1831 dev_dbg(dev, "shutdown\n"); 1842 dev_dbg(dev, "shutdown\n");
1832 dev->driver->shutdown(dev); 1843 dev->driver->shutdown(dev);
1833 } 1844 }
1845
1846 device_unlock(dev);
1847 if (dev->parent)
1848 device_unlock(dev->parent);
1849
1834 put_device(dev); 1850 put_device(dev);
1851 put_device(dev->parent);
1835 1852
1836 spin_lock(&devices_kset->list_lock); 1853 spin_lock(&devices_kset->list_lock);
1837 } 1854 }