proc, coredump: add CoreDumping flag to /proc/pid/status
[platform/kernel/linux-exynos.git] / drivers / base / core.c
index a359934..1c67bf2 100644 (file)
@@ -217,6 +217,13 @@ struct device_link *device_link_add(struct device *consumer,
                        link->rpm_active = true;
                }
                pm_runtime_new_link(consumer);
+               /*
+                * If the link is being added by the consumer driver at probe
+                * time, balance the decrementation of the supplier's runtime PM
+                * usage counter after consumer probe in driver_probe_device().
+                */
+               if (consumer->links.status == DL_DEV_PROBING)
+                       pm_runtime_get_noresume(supplier);
        }
        get_device(supplier);
        link->supplier = supplier;
@@ -235,12 +242,12 @@ struct device_link *device_link_add(struct device *consumer,
                        switch (consumer->links.status) {
                        case DL_DEV_PROBING:
                                /*
-                                * Balance the decrementation of the supplier's
-                                * runtime PM usage counter after consumer probe
-                                * in driver_probe_device().
+                                * Some callers expect the link creation during
+                                * consumer driver probe to resume the supplier
+                                * even without DL_FLAG_RPM_ACTIVE.
                                 */
                                if (flags & DL_FLAG_PM_RUNTIME)
-                                       pm_runtime_get_sync(supplier);
+                                       pm_runtime_resume(supplier);
 
                                link->status = DL_STATE_CONSUMER_PROBE;
                                break;
@@ -984,8 +991,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;
 }
@@ -1564,6 +1577,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);
 }
@@ -1966,7 +1981,6 @@ void device_del(struct device *dev)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DEL_DEVICE, dev);
 
-       device_links_purge(dev);
        dpm_sysfs_remove(dev);
        if (parent)
                klist_del(&dev->p->knode_parent);
@@ -1994,6 +2008,7 @@ void device_del(struct device *dev)
        device_pm_remove(dev);
        driver_deferred_probe_del(dev);
        device_remove_properties(dev);
+       device_links_purge(dev);
 
        /* Notify the platform of the removal, in case they
         * need to do anything...
@@ -2776,6 +2791,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.