drivercore: Output common devicetree information in uevent
authorGrant Likely <grant.likely@secretlab.ca>
Wed, 1 Feb 2012 18:22:22 +0000 (11:22 -0700)
committerGrant Likely <grant.likely@secretlab.ca>
Wed, 1 Feb 2012 21:26:30 +0000 (14:26 -0700)
When userspace needs to find a specific device, it currently isn't easy to
resolve a /sys/devices/ path from a specific device tree node.  Nor is it
easy to obtain the compatible list for devices.

This patch generalizes the code that inserts OF_* values into the uevent
device attribute so that any device that is attached to an OF node will
have that information exported to userspace.  Without this patch only
platform devices and some powerpc-specific busses have access to this
data.

The original function also creates a MODALIAS property for the compatible
list, but that code has not been generalized into the common case because
it has the potential to break module loading on a lot of bus types.  Bus
types are still responsible for their own MODALIAS properties.

Boot tested on ARM and compile tested on PowerPC and SPARC.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Tobias Klauser <tklauser@distanz.ch>
Cc: Frederic Lambert <frdrc66@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@sirena.org.uk>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/ibmebus.c
drivers/base/core.c
drivers/base/platform.c
drivers/macintosh/macio_asic.c
drivers/of/device.c
include/linux/of_device.h

index d39ae606ff8db4e0cc7286cb6393ca9dace0ab4b..79bb282e650161d8478887fde87cb9d99e00c97f 100644 (file)
@@ -713,7 +713,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
 
 struct bus_type ibmebus_bus_type = {
        .name      = "ibmebus",
-       .uevent    = of_device_uevent,
+       .uevent    = of_device_uevent_modalias,
        .bus_attrs = ibmebus_bus_attrs,
        .match     = ibmebus_bus_bus_match,
        .probe     = ibmebus_bus_device_probe,
index 4a67cc0c8b37aaeeec97e27eef04752a52504d1a..28d8c21bb323d6072a32062bd08c2cef9b86db66 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/string.h>
 #include <linux/kdev_t.h>
 #include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/genhd.h>
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
@@ -267,6 +269,9 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
        if (dev->driver)
                add_uevent_var(env, "DRIVER=%s", dev->driver->name);
 
+       /* Add common DT information about the device */
+       of_device_uevent(dev, env);
+
        /* have the bus specific function add its stuff */
        if (dev->bus && dev->bus->uevent) {
                retval = dev->bus->uevent(dev, env);
index f0c605e99ade2816c7c998efb4e19f1264b9ca81..a1a72250258705eb059b6601b086cf9d296b1d1b 100644 (file)
@@ -621,7 +621,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
        int rc;
 
        /* Some devices have extra OF data and an OF-style MODALIAS */
-       rc = of_device_uevent(dev,env);
+       rc = of_device_uevent_modalias(dev,env);
        if (rc != -ENODEV)
                return rc;
 
index 4daf9e5a7736f415023ff1ce07d6cb2d79d526b9..20e5c2cda430e9f0a8ffbab8fbd1fc7e2f8dbf8b 100644 (file)
@@ -137,7 +137,7 @@ extern struct device_attribute macio_dev_attrs[];
 struct bus_type macio_bus_type = {
        .name   = "macio",
        .match  = macio_bus_match,
-       .uevent = of_device_uevent,
+       .uevent = of_device_uevent_modalias,
        .probe  = macio_device_probe,
        .remove = macio_device_remove,
        .shutdown = macio_device_shutdown,
index 62b4b32ac8878eb13ca06ab57cc014a4ba843dfe..4c74e4fc5a5190857be5eaa749b82284ee8a2fb1 100644 (file)
@@ -128,39 +128,41 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
 /**
  * of_device_uevent - Display OF related uevent information
  */
-int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        const char *compat;
        int seen = 0, cplen, sl;
 
        if ((!dev) || (!dev->of_node))
-               return -ENODEV;
-
-       if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name))
-               return -ENOMEM;
+               return;
 
-       if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type))
-               return -ENOMEM;
+       add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
+       add_uevent_var(env, "OF_FULLNAME=%s", dev->of_node->full_name);
+       if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
+               add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
 
        /* Since the compatible field can contain pretty much anything
         * it's not really legal to split it out with commas. We split it
         * up using a number of environment variables instead. */
-
        compat = of_get_property(dev->of_node, "compatible", &cplen);
        while (compat && *compat && cplen > 0) {
-               if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
-                       return -ENOMEM;
-
+               add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
                sl = strlen(compat) + 1;
                compat += sl;
                cplen -= sl;
                seen++;
        }
+       add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
+}
 
-       if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
-               return -ENOMEM;
+int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
+{
+       int sl;
+
+       if ((!dev) || (!dev->of_node))
+               return -ENODEV;
 
-       /* modalias is trickier, we add it in 2 steps */
+       /* Devicetree modalias is tricky, we add it in 2 steps */
        if (add_uevent_var(env, "MODALIAS="))
                return -ENOMEM;
 
index ae5638480ef22141f0699854d4b59fbba57aeffe..cbc42143fa5bb6f3124704c1f59775f02f624856 100644 (file)
@@ -34,7 +34,8 @@ extern void of_device_unregister(struct platform_device *ofdev);
 extern ssize_t of_device_get_modalias(struct device *dev,
                                        char *str, ssize_t len);
 
-extern int of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
+extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
+extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env);
 
 static inline void of_device_node_put(struct device *dev)
 {
@@ -49,7 +50,10 @@ static inline int of_driver_match_device(struct device *dev,
        return 0;
 }
 
-static inline int of_device_uevent(struct device *dev,
+static inline void of_device_uevent(struct device *dev,
+                       struct kobj_uevent_env *env) { }
+
+static inline int of_device_uevent_modalias(struct device *dev,
                                   struct kobj_uevent_env *env)
 {
        return -ENODEV;