aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-03-12 14:30:05 -0400
committerTejun Heo <tj@kernel.org>2013-03-12 14:36:35 -0400
commitd73ce004225a7b2ed75f4340bb63721d55552265 (patch)
treefa4b2ab4f064412018589307b988567a713b6d96
parent6dbe51c251a327e012439c4772097a13df43c5b8 (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.h2
-rw-r--r--drivers/base/bus.c73
-rw-r--r--drivers/base/core.c2
-rw-r--r--include/linux/device.h2
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; }
101extern int platform_bus_init(void); 101extern int platform_bus_init(void);
102extern void cpu_dev_init(void); 102extern void cpu_dev_init(void);
103 103
104struct kobject *virtual_device_parent(struct device *dev);
105
104extern int bus_add_device(struct device *dev); 106extern int bus_add_device(struct device *dev);
105extern void bus_probe_device(struct device *dev); 107extern void bus_probe_device(struct device *dev);
106extern void bus_remove_device(struct device *dev); 108extern 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/ 1209static 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 */
1226int 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 */
1269int subsys_system_register(struct bus_type *subsys,
1270 const struct attribute_group **groups)
1271{
1272 return subsys_register(subsys, groups, &system_kset->kobj);
1273}
1266EXPORT_SYMBOL_GPL(subsys_system_register); 1274EXPORT_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 */
1287int 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
1268int __init buses_init(void) 1299int __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
693static struct kobject *virtual_device_parent(struct device *dev) 693struct 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
303int subsys_system_register(struct bus_type *subsys, 303int subsys_system_register(struct bus_type *subsys,
304 const struct attribute_group **groups); 304 const struct attribute_group **groups);
305int 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