diff options
author | Tejun Heo <tj@kernel.org> | 2013-03-12 14:30:05 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-03-12 14:36:35 -0400 |
commit | d73ce004225a7b2ed75f4340bb63721d55552265 (patch) | |
tree | fa4b2ab4f064412018589307b988567a713b6d96 | |
parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (diff) |
driver/base: implement subsys_virtual_register()
Kay tells me the most appropriate place to expose workqueues to
userland would be /sys/devices/virtual/workqueues/WQ_NAME which is
symlinked to /sys/bus/workqueue/devices/WQ_NAME and that we're lacking
a way to do that outside of driver core as virtual_device_parent()
isn't exported and there's no inteface to conveniently create a
virtual subsystem.
This patch implements subsys_virtual_register() by factoring out
subsys_register() from subsys_system_register() and using it with
virtual_device_parent() as the origin directory. It's identical to
subsys_system_register() other than the origin directory but we aren't
gonna restrict the device names which should be used under it.
This will be used to expose workqueue attributes to userland.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Kay Sievers <kay.sievers@vrfy.org>
-rw-r--r-- | drivers/base/base.h | 2 | ||||
-rw-r--r-- | drivers/base/bus.c | 73 | ||||
-rw-r--r-- | drivers/base/core.c | 2 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
4 files changed, 57 insertions, 22 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index 6ee17bb391a9..b8bdfe61daa6 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -101,6 +101,8 @@ static inline int hypervisor_init(void) { return 0; } | |||
101 | extern int platform_bus_init(void); | 101 | extern int platform_bus_init(void); |
102 | extern void cpu_dev_init(void); | 102 | extern void cpu_dev_init(void); |
103 | 103 | ||
104 | struct kobject *virtual_device_parent(struct device *dev); | ||
105 | |||
104 | extern int bus_add_device(struct device *dev); | 106 | extern int bus_add_device(struct device *dev); |
105 | extern void bus_probe_device(struct device *dev); | 107 | extern void bus_probe_device(struct device *dev); |
106 | extern void bus_remove_device(struct device *dev); | 108 | extern void bus_remove_device(struct device *dev); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 519865b53f76..2ae2d2f92b6b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -1205,26 +1205,10 @@ static void system_root_device_release(struct device *dev) | |||
1205 | { | 1205 | { |
1206 | kfree(dev); | 1206 | kfree(dev); |
1207 | } | 1207 | } |
1208 | /** | 1208 | |
1209 | * subsys_system_register - register a subsystem at /sys/devices/system/ | 1209 | static int subsys_register(struct bus_type *subsys, |
1210 | * @subsys: system subsystem | 1210 | const struct attribute_group **groups, |
1211 | * @groups: default attributes for the root device | 1211 | struct kobject *parent_of_root) |
1212 | * | ||
1213 | * All 'system' subsystems have a /sys/devices/system/<name> root device | ||
1214 | * with the name of the subsystem. The root device can carry subsystem- | ||
1215 | * wide attributes. All registered devices are below this single root | ||
1216 | * device and are named after the subsystem with a simple enumeration | ||
1217 | * number appended. The registered devices are not explicitely named; | ||
1218 | * only 'id' in the device needs to be set. | ||
1219 | * | ||
1220 | * Do not use this interface for anything new, it exists for compatibility | ||
1221 | * with bad ideas only. New subsystems should use plain subsystems; and | ||
1222 | * add the subsystem-wide attributes should be added to the subsystem | ||
1223 | * directory itself and not some create fake root-device placed in | ||
1224 | * /sys/devices/system/<name>. | ||
1225 | */ | ||
1226 | int subsys_system_register(struct bus_type *subsys, | ||
1227 | const struct attribute_group **groups) | ||
1228 | { | 1212 | { |
1229 | struct device *dev; | 1213 | struct device *dev; |
1230 | int err; | 1214 | int err; |
@@ -1243,7 +1227,7 @@ int subsys_system_register(struct bus_type *subsys, | |||
1243 | if (err < 0) | 1227 | if (err < 0) |
1244 | goto err_name; | 1228 | goto err_name; |
1245 | 1229 | ||
1246 | dev->kobj.parent = &system_kset->kobj; | 1230 | dev->kobj.parent = parent_of_root; |
1247 | dev->groups = groups; | 1231 | dev->groups = groups; |
1248 | dev->release = system_root_device_release; | 1232 | dev->release = system_root_device_release; |
1249 | 1233 | ||
@@ -1263,8 +1247,55 @@ err_dev: | |||
1263 | bus_unregister(subsys); | 1247 | bus_unregister(subsys); |
1264 | return err; | 1248 | return err; |
1265 | } | 1249 | } |
1250 | |||
1251 | /** | ||
1252 | * subsys_system_register - register a subsystem at /sys/devices/system/ | ||
1253 | * @subsys: system subsystem | ||
1254 | * @groups: default attributes for the root device | ||
1255 | * | ||
1256 | * All 'system' subsystems have a /sys/devices/system/<name> root device | ||
1257 | * with the name of the subsystem. The root device can carry subsystem- | ||
1258 | * wide attributes. All registered devices are below this single root | ||
1259 | * device and are named after the subsystem with a simple enumeration | ||
1260 | * number appended. The registered devices are not explicitely named; | ||
1261 | * only 'id' in the device needs to be set. | ||
1262 | * | ||
1263 | * Do not use this interface for anything new, it exists for compatibility | ||
1264 | * with bad ideas only. New subsystems should use plain subsystems; and | ||
1265 | * add the subsystem-wide attributes should be added to the subsystem | ||
1266 | * directory itself and not some create fake root-device placed in | ||
1267 | * /sys/devices/system/<name>. | ||
1268 | */ | ||
1269 | int subsys_system_register(struct bus_type *subsys, | ||
1270 | const struct attribute_group **groups) | ||
1271 | { | ||
1272 | return subsys_register(subsys, groups, &system_kset->kobj); | ||
1273 | } | ||
1266 | EXPORT_SYMBOL_GPL(subsys_system_register); | 1274 | EXPORT_SYMBOL_GPL(subsys_system_register); |
1267 | 1275 | ||
1276 | /** | ||
1277 | * subsys_virtual_register - register a subsystem at /sys/devices/virtual/ | ||
1278 | * @subsys: virtual subsystem | ||
1279 | * @groups: default attributes for the root device | ||
1280 | * | ||
1281 | * All 'virtual' subsystems have a /sys/devices/system/<name> root device | ||
1282 | * with the name of the subystem. The root device can carry subsystem-wide | ||
1283 | * attributes. All registered devices are below this single root device. | ||
1284 | * There's no restriction on device naming. This is for kernel software | ||
1285 | * constructs which need sysfs interface. | ||
1286 | */ | ||
1287 | int subsys_virtual_register(struct bus_type *subsys, | ||
1288 | const struct attribute_group **groups) | ||
1289 | { | ||
1290 | struct kobject *virtual_dir; | ||
1291 | |||
1292 | virtual_dir = virtual_device_parent(NULL); | ||
1293 | if (!virtual_dir) | ||
1294 | return -ENOMEM; | ||
1295 | |||
1296 | return subsys_register(subsys, groups, virtual_dir); | ||
1297 | } | ||
1298 | |||
1268 | int __init buses_init(void) | 1299 | int __init buses_init(void) |
1269 | { | 1300 | { |
1270 | bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); | 1301 | bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 56536f4b0f6b..f58084a86e8c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -690,7 +690,7 @@ void device_initialize(struct device *dev) | |||
690 | set_dev_node(dev, -1); | 690 | set_dev_node(dev, -1); |
691 | } | 691 | } |
692 | 692 | ||
693 | static struct kobject *virtual_device_parent(struct device *dev) | 693 | struct kobject *virtual_device_parent(struct device *dev) |
694 | { | 694 | { |
695 | static struct kobject *virtual_dir = NULL; | 695 | static struct kobject *virtual_dir = NULL; |
696 | 696 | ||
diff --git a/include/linux/device.h b/include/linux/device.h index 9d6464ea99c6..ee10d4e7be1a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -302,6 +302,8 @@ void subsys_interface_unregister(struct subsys_interface *sif); | |||
302 | 302 | ||
303 | int subsys_system_register(struct bus_type *subsys, | 303 | int subsys_system_register(struct bus_type *subsys, |
304 | const struct attribute_group **groups); | 304 | const struct attribute_group **groups); |
305 | int subsys_virtual_register(struct bus_type *subsys, | ||
306 | const struct attribute_group **groups); | ||
305 | 307 | ||
306 | /** | 308 | /** |
307 | * struct class - device classes | 309 | * struct class - device classes |