Merge tag 'cpumask-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty...
[deliverable/linux.git] / drivers / base / core.c
index 846d12b5d5794942b743a53c1c8fd513358995d9..f338037a4f3d9109e4d69da7a22a4e41070615b4 100644 (file)
@@ -85,14 +85,13 @@ const char *dev_driver_string(const struct device *dev)
 }
 EXPORT_SYMBOL(dev_driver_string);
 
-#define to_dev(obj) container_of(obj, struct device, kobj)
 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
 
 static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
                             char *buf)
 {
        struct device_attribute *dev_attr = to_dev_attr(attr);
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
        ssize_t ret = -EIO;
 
        if (dev_attr->show)
@@ -108,7 +107,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
                              const char *buf, size_t count)
 {
        struct device_attribute *dev_attr = to_dev_attr(attr);
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
        ssize_t ret = -EIO;
 
        if (dev_attr->store)
@@ -182,7 +181,7 @@ EXPORT_SYMBOL_GPL(device_show_int);
  */
 static void device_release(struct kobject *kobj)
 {
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct device_private *p = dev->p;
 
        if (dev->release)
@@ -200,7 +199,7 @@ static void device_release(struct kobject *kobj)
 
 static const void *device_namespace(struct kobject *kobj)
 {
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
        const void *ns = NULL;
 
        if (dev->class && dev->class->ns_type)
@@ -221,7 +220,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
        struct kobj_type *ktype = get_ktype(kobj);
 
        if (ktype == &device_ktype) {
-               struct device *dev = to_dev(kobj);
+               struct device *dev = kobj_to_dev(kobj);
                if (dev->bus)
                        return 1;
                if (dev->class)
@@ -232,7 +231,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
 
 static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
 {
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
 
        if (dev->bus)
                return dev->bus->name;
@@ -244,7 +243,7 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
 static int dev_uevent(struct kset *kset, struct kobject *kobj,
                      struct kobj_uevent_env *env)
 {
-       struct device *dev = to_dev(kobj);
+       struct device *dev = kobj_to_dev(kobj);
        int retval = 0;
 
        /* add device node properties if present */
@@ -1132,7 +1131,7 @@ int device_register(struct device *dev)
  */
 struct device *get_device(struct device *dev)
 {
-       return dev ? to_dev(kobject_get(&dev->kobj)) : NULL;
+       return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
 }
 
 /**
@@ -1812,6 +1811,13 @@ void device_shutdown(void)
        while (!list_empty(&devices_kset->list)) {
                dev = list_entry(devices_kset->list.prev, struct device,
                                kobj.entry);
+
+               /*
+                * hold reference count of device's parent to
+                * prevent it from being freed because parent's
+                * lock is to be held
+                */
+               get_device(dev->parent);
                get_device(dev);
                /*
                 * Make sure the device is off the kset list, in the
@@ -1820,6 +1826,11 @@ void device_shutdown(void)
                list_del_init(&dev->kobj.entry);
                spin_unlock(&devices_kset->list_lock);
 
+               /* hold lock to avoid race with probe/release */
+               if (dev->parent)
+                       device_lock(dev->parent);
+               device_lock(dev);
+
                /* Don't allow any more runtime suspends */
                pm_runtime_get_noresume(dev);
                pm_runtime_barrier(dev);
@@ -1831,7 +1842,13 @@ void device_shutdown(void)
                        dev_dbg(dev, "shutdown\n");
                        dev->driver->shutdown(dev);
                }
+
+               device_unlock(dev);
+               if (dev->parent)
+                       device_unlock(dev->parent);
+
                put_device(dev);
+               put_device(dev->parent);
 
                spin_lock(&devices_kset->list_lock);
        }
This page took 0.026824 seconds and 5 git commands to generate.