]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/base/core.c
drivers/base: Introduce kill_device()
[mirror_ubuntu-bionic-kernel.git] / drivers / base / core.c
index a9840cca9857d97d903e8994f2d7708480d37971..ddfaf230292c68cff999bcdfc739ff7593cde6dd 100644 (file)
@@ -1000,8 +1000,14 @@ out:
 static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
 {
-       if (kobject_synth_uevent(&dev->kobj, buf, count))
+       int rc;
+
+       rc = kobject_synth_uevent(&dev->kobj, buf, count);
+
+       if (rc) {
                dev_err(dev, "uevent: failed to send synthetic uevent\n");
+               return rc;
+       }
 
        return count;
 }
@@ -1580,6 +1586,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
                return;
 
        mutex_lock(&gdp_mutex);
+       if (!kobject_has_children(glue_dir))
+               kobject_del(glue_dir);
        kobject_put(glue_dir);
        mutex_unlock(&gdp_mutex);
 }
@@ -1956,6 +1964,24 @@ void put_device(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(put_device);
 
+bool kill_device(struct device *dev)
+{
+       /*
+        * Require the device lock and set the "dead" flag to guarantee that
+        * the update behavior is consistent with the other bitfields near
+        * it and that we cannot have an asynchronous probe routine trying
+        * to run while we are tearing out the bus/class/sysfs from
+        * underneath the device.
+        */
+       lockdep_assert_held(&dev->mutex);
+
+       if (dev->p->dead)
+               return false;
+       dev->p->dead = true;
+       return true;
+}
+EXPORT_SYMBOL_GPL(kill_device);
+
 /**
  * device_del - delete device from system.
  * @dev: device.
@@ -1975,6 +2001,10 @@ void device_del(struct device *dev)
        struct kobject *glue_dir = NULL;
        struct class_interface *class_intf;
 
+       device_lock(dev);
+       kill_device(dev);
+       device_unlock(dev);
+
        /* Notify clients of device removal.  This call must come
         * before dpm_sysfs_remove().
         */
@@ -2792,6 +2822,9 @@ void device_shutdown(void)
 {
        struct device *dev, *parent;
 
+       wait_for_device_probe();
+       device_block_probing();
+
        spin_lock(&devices_kset->list_lock);
        /*
         * Walk the devices list backward, shutting down each in turn.