aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2012-02-01 13:22:22 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-02-01 16:26:30 -0500
commit07d57a32fb6eb2da017796e038682f817a4f685e (patch)
tree4c7bb83cbda8db99ed91f575d8355c5b45b16cfb
parent7aff0fe33033fc75b61446ba29d38b1b1354af9f (diff)
drivercore: Output common devicetree information in uevent
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>
-rw-r--r--arch/powerpc/kernel/ibmebus.c2
-rw-r--r--drivers/base/core.c5
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/macintosh/macio_asic.c2
-rw-r--r--drivers/of/device.c30
-rw-r--r--include/linux/of_device.h8
6 files changed, 30 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index d39ae606ff8d..79bb282e6501 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -713,7 +713,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
713 713
714struct bus_type ibmebus_bus_type = { 714struct bus_type ibmebus_bus_type = {
715 .name = "ibmebus", 715 .name = "ibmebus",
716 .uevent = of_device_uevent, 716 .uevent = of_device_uevent_modalias,
717 .bus_attrs = ibmebus_bus_attrs, 717 .bus_attrs = ibmebus_bus_attrs,
718 .match = ibmebus_bus_bus_match, 718 .match = ibmebus_bus_bus_match,
719 .probe = ibmebus_bus_device_probe, 719 .probe = ibmebus_bus_device_probe,
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4a67cc0c8b37..28d8c21bb323 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -18,6 +18,8 @@
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/kdev_t.h> 19#include <linux/kdev_t.h>
20#include <linux/notifier.h> 20#include <linux/notifier.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
21#include <linux/genhd.h> 23#include <linux/genhd.h>
22#include <linux/kallsyms.h> 24#include <linux/kallsyms.h>
23#include <linux/mutex.h> 25#include <linux/mutex.h>
@@ -267,6 +269,9 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
267 if (dev->driver) 269 if (dev->driver)
268 add_uevent_var(env, "DRIVER=%s", dev->driver->name); 270 add_uevent_var(env, "DRIVER=%s", dev->driver->name);
269 271
272 /* Add common DT information about the device */
273 of_device_uevent(dev, env);
274
270 /* have the bus specific function add its stuff */ 275 /* have the bus specific function add its stuff */
271 if (dev->bus && dev->bus->uevent) { 276 if (dev->bus && dev->bus->uevent) {
272 retval = dev->bus->uevent(dev, env); 277 retval = dev->bus->uevent(dev, env);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index f0c605e99ade..a1a722502587 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -621,7 +621,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
621 int rc; 621 int rc;
622 622
623 /* Some devices have extra OF data and an OF-style MODALIAS */ 623 /* Some devices have extra OF data and an OF-style MODALIAS */
624 rc = of_device_uevent(dev,env); 624 rc = of_device_uevent_modalias(dev,env);
625 if (rc != -ENODEV) 625 if (rc != -ENODEV)
626 return rc; 626 return rc;
627 627
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 4daf9e5a7736..20e5c2cda430 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -137,7 +137,7 @@ extern struct device_attribute macio_dev_attrs[];
137struct bus_type macio_bus_type = { 137struct bus_type macio_bus_type = {
138 .name = "macio", 138 .name = "macio",
139 .match = macio_bus_match, 139 .match = macio_bus_match,
140 .uevent = of_device_uevent, 140 .uevent = of_device_uevent_modalias,
141 .probe = macio_device_probe, 141 .probe = macio_device_probe,
142 .remove = macio_device_remove, 142 .remove = macio_device_remove,
143 .shutdown = macio_device_shutdown, 143 .shutdown = macio_device_shutdown,
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 62b4b32ac887..4c74e4fc5a51 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -128,39 +128,41 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
128/** 128/**
129 * of_device_uevent - Display OF related uevent information 129 * of_device_uevent - Display OF related uevent information
130 */ 130 */
131int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) 131void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
132{ 132{
133 const char *compat; 133 const char *compat;
134 int seen = 0, cplen, sl; 134 int seen = 0, cplen, sl;
135 135
136 if ((!dev) || (!dev->of_node)) 136 if ((!dev) || (!dev->of_node))
137 return -ENODEV; 137 return;
138
139 if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name))
140 return -ENOMEM;
141 138
142 if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type)) 139 add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
143 return -ENOMEM; 140 add_uevent_var(env, "OF_FULLNAME=%s", dev->of_node->full_name);
141 if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
142 add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
144 143
145 /* Since the compatible field can contain pretty much anything 144 /* Since the compatible field can contain pretty much anything
146 * it's not really legal to split it out with commas. We split it 145 * it's not really legal to split it out with commas. We split it
147 * up using a number of environment variables instead. */ 146 * up using a number of environment variables instead. */
148
149 compat = of_get_property(dev->of_node, "compatible", &cplen); 147 compat = of_get_property(dev->of_node, "compatible", &cplen);
150 while (compat && *compat && cplen > 0) { 148 while (compat && *compat && cplen > 0) {
151 if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) 149 add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
152 return -ENOMEM;
153
154 sl = strlen(compat) + 1; 150 sl = strlen(compat) + 1;
155 compat += sl; 151 compat += sl;
156 cplen -= sl; 152 cplen -= sl;
157 seen++; 153 seen++;
158 } 154 }
155 add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
156}
159 157
160 if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) 158int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
161 return -ENOMEM; 159{
160 int sl;
161
162 if ((!dev) || (!dev->of_node))
163 return -ENODEV;
162 164
163 /* modalias is trickier, we add it in 2 steps */ 165 /* Devicetree modalias is tricky, we add it in 2 steps */
164 if (add_uevent_var(env, "MODALIAS=")) 166 if (add_uevent_var(env, "MODALIAS="))
165 return -ENOMEM; 167 return -ENOMEM;
166 168
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index ae5638480ef2..cbc42143fa5b 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -34,7 +34,8 @@ extern void of_device_unregister(struct platform_device *ofdev);
34extern ssize_t of_device_get_modalias(struct device *dev, 34extern ssize_t of_device_get_modalias(struct device *dev,
35 char *str, ssize_t len); 35 char *str, ssize_t len);
36 36
37extern int of_device_uevent(struct device *dev, struct kobj_uevent_env *env); 37extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
38extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env);
38 39
39static inline void of_device_node_put(struct device *dev) 40static inline void of_device_node_put(struct device *dev)
40{ 41{
@@ -49,7 +50,10 @@ static inline int of_driver_match_device(struct device *dev,
49 return 0; 50 return 0;
50} 51}
51 52
52static inline int of_device_uevent(struct device *dev, 53static inline void of_device_uevent(struct device *dev,
54 struct kobj_uevent_env *env) { }
55
56static inline int of_device_uevent_modalias(struct device *dev,
53 struct kobj_uevent_env *env) 57 struct kobj_uevent_env *env)
54{ 58{
55 return -ENODEV; 59 return -ENODEV;