PM / Driver Core: Kill dev_pm_ops platform warning for now
[safe/jmp/linux-2.6] / drivers / base / core.c
index 1977d4b..7ecb193 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/semaphore.h>
 #include <linux/mutex.h>
+#include <linux/async.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -161,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
        struct device *dev = to_dev(kobj);
        int retval = 0;
 
-       /* add the major/minor if present */
+       /* add device node properties if present */
        if (MAJOR(dev->devt)) {
+               const char *tmp;
+               const char *name;
+
                add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
                add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
+               name = device_get_nodename(dev, &tmp);
+               if (name) {
+                       add_uevent_var(env, "DEVNAME=%s", name);
+                       kfree(tmp);
+               }
        }
 
        if (dev->type && dev->type->name)
@@ -874,7 +883,7 @@ int device_add(struct device *dev)
         * the name, and force the use of dev_name()
         */
        if (dev->init_name) {
-               dev_set_name(dev, dev->init_name);
+               dev_set_name(dev, "%s", dev->init_name);
                dev->init_name = NULL;
        }
 
@@ -1128,6 +1137,47 @@ static struct device *next_device(struct klist_iter *i)
 }
 
 /**
+ * device_get_nodename - path of device node file
+ * @dev: device
+ * @tmp: possibly allocated string
+ *
+ * Return the relative path of a possible device node.
+ * Non-default names may need to allocate a memory to compose
+ * a name. This memory is returned in tmp and needs to be
+ * freed by the caller.
+ */
+const char *device_get_nodename(struct device *dev, const char **tmp)
+{
+       char *s;
+
+       *tmp = NULL;
+
+       /* the device type may provide a specific name */
+       if (dev->type && dev->type->nodename)
+               *tmp = dev->type->nodename(dev);
+       if (*tmp)
+               return *tmp;
+
+       /* the class may provide a specific name */
+       if (dev->class && dev->class->nodename)
+               *tmp = dev->class->nodename(dev);
+       if (*tmp)
+               return *tmp;
+
+       /* return name without allocation, tmp == NULL */
+       if (strchr(dev_name(dev), '!') == NULL)
+               return dev_name(dev);
+
+       /* replace '!' in the name with '/' */
+       *tmp = kstrdup(dev_name(dev), GFP_KERNEL);
+       if (!*tmp)
+               return NULL;
+       while ((s = strchr(*tmp, '!')))
+               s[0] = '/';
+       return *tmp;
+}
+
+/**
  * device_for_each_child - device child iterator.
  * @parent: parent struct device.
  * @data: data for the callback.
@@ -1271,7 +1321,7 @@ struct device *__root_device_register(const char *name, struct module *owner)
        if (!root)
                return ERR_PTR(err);
 
-       err = dev_set_name(&root->dev, name);
+       err = dev_set_name(&root->dev, "%s", name);
        if (err) {
                kfree(root);
                return ERR_PTR(err);
@@ -1665,4 +1715,5 @@ void device_shutdown(void)
        kobject_put(sysfs_dev_char_kobj);
        kobject_put(sysfs_dev_block_kobj);
        kobject_put(dev_kobj);
+       async_synchronize_full();
 }