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>
This commit is contained in:
Родитель
6dbe51c251
Коммит
d73ce00422
|
@ -101,6 +101,8 @@ static inline int hypervisor_init(void) { return 0; }
|
|||
extern int platform_bus_init(void);
|
||||
extern void cpu_dev_init(void);
|
||||
|
||||
struct kobject *virtual_device_parent(struct device *dev);
|
||||
|
||||
extern int bus_add_device(struct device *dev);
|
||||
extern void bus_probe_device(struct device *dev);
|
||||
extern void bus_remove_device(struct device *dev);
|
||||
|
|
|
@ -1205,6 +1205,49 @@ static void system_root_device_release(struct device *dev)
|
|||
{
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static int subsys_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups,
|
||||
struct kobject *parent_of_root)
|
||||
{
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
err = bus_register(subsys);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_dev;
|
||||
}
|
||||
|
||||
err = dev_set_name(dev, "%s", subsys->name);
|
||||
if (err < 0)
|
||||
goto err_name;
|
||||
|
||||
dev->kobj.parent = parent_of_root;
|
||||
dev->groups = groups;
|
||||
dev->release = system_root_device_release;
|
||||
|
||||
err = device_register(dev);
|
||||
if (err < 0)
|
||||
goto err_dev_reg;
|
||||
|
||||
subsys->dev_root = dev;
|
||||
return 0;
|
||||
|
||||
err_dev_reg:
|
||||
put_device(dev);
|
||||
dev = NULL;
|
||||
err_name:
|
||||
kfree(dev);
|
||||
err_dev:
|
||||
bus_unregister(subsys);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* subsys_system_register - register a subsystem at /sys/devices/system/
|
||||
* @subsys: system subsystem
|
||||
|
@ -1226,45 +1269,33 @@ static void system_root_device_release(struct device *dev)
|
|||
int subsys_system_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
err = bus_register(subsys);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_dev;
|
||||
}
|
||||
|
||||
err = dev_set_name(dev, "%s", subsys->name);
|
||||
if (err < 0)
|
||||
goto err_name;
|
||||
|
||||
dev->kobj.parent = &system_kset->kobj;
|
||||
dev->groups = groups;
|
||||
dev->release = system_root_device_release;
|
||||
|
||||
err = device_register(dev);
|
||||
if (err < 0)
|
||||
goto err_dev_reg;
|
||||
|
||||
subsys->dev_root = dev;
|
||||
return 0;
|
||||
|
||||
err_dev_reg:
|
||||
put_device(dev);
|
||||
dev = NULL;
|
||||
err_name:
|
||||
kfree(dev);
|
||||
err_dev:
|
||||
bus_unregister(subsys);
|
||||
return err;
|
||||
return subsys_register(subsys, groups, &system_kset->kobj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_system_register);
|
||||
|
||||
/**
|
||||
* subsys_virtual_register - register a subsystem at /sys/devices/virtual/
|
||||
* @subsys: virtual subsystem
|
||||
* @groups: default attributes for the root device
|
||||
*
|
||||
* All 'virtual' subsystems have a /sys/devices/system/<name> root device
|
||||
* with the name of the subystem. The root device can carry subsystem-wide
|
||||
* attributes. All registered devices are below this single root device.
|
||||
* There's no restriction on device naming. This is for kernel software
|
||||
* constructs which need sysfs interface.
|
||||
*/
|
||||
int subsys_virtual_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
struct kobject *virtual_dir;
|
||||
|
||||
virtual_dir = virtual_device_parent(NULL);
|
||||
if (!virtual_dir)
|
||||
return -ENOMEM;
|
||||
|
||||
return subsys_register(subsys, groups, virtual_dir);
|
||||
}
|
||||
|
||||
int __init buses_init(void)
|
||||
{
|
||||
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
|
||||
|
|
|
@ -690,7 +690,7 @@ void device_initialize(struct device *dev)
|
|||
set_dev_node(dev, -1);
|
||||
}
|
||||
|
||||
static struct kobject *virtual_device_parent(struct device *dev)
|
||||
struct kobject *virtual_device_parent(struct device *dev)
|
||||
{
|
||||
static struct kobject *virtual_dir = NULL;
|
||||
|
||||
|
|
|
@ -302,6 +302,8 @@ void subsys_interface_unregister(struct subsys_interface *sif);
|
|||
|
||||
int subsys_system_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups);
|
||||
int subsys_virtual_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups);
|
||||
|
||||
/**
|
||||
* struct class - device classes
|
||||
|
|
Загрузка…
Ссылка в новой задаче