forked from Minki/linux
driver core: add root_device_register()
Add support for allocating root device objects which group device objects under /sys/devices directories. Also add a sysfs 'module' symlink which points to the owner of the root device object. This symlink will be used in virtio to allow userspace to determine which virtio bus implementation a given device is associated with. [Includes suggestions from Cornelia Huck] Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
7232800ba8
commit
0aa0dc41bf
@ -1217,6 +1217,97 @@ EXPORT_SYMBOL_GPL(put_device);
|
||||
EXPORT_SYMBOL_GPL(device_create_file);
|
||||
EXPORT_SYMBOL_GPL(device_remove_file);
|
||||
|
||||
struct root_device
|
||||
{
|
||||
struct device dev;
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
#define to_root_device(dev) container_of(dev, struct root_device, dev)
|
||||
|
||||
static void root_device_release(struct device *dev)
|
||||
{
|
||||
kfree(to_root_device(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* __root_device_register - allocate and register a root device
|
||||
* @name: root device name
|
||||
* @owner: owner module of the root device, usually THIS_MODULE
|
||||
*
|
||||
* This function allocates a root device and registers it
|
||||
* using device_register(). In order to free the returned
|
||||
* device, use root_device_unregister().
|
||||
*
|
||||
* Root devices are dummy devices which allow other devices
|
||||
* to be grouped under /sys/devices. Use this function to
|
||||
* allocate a root device and then use it as the parent of
|
||||
* any device which should appear under /sys/devices/{name}
|
||||
*
|
||||
* The /sys/devices/{name} directory will also contain a
|
||||
* 'module' symlink which points to the @owner directory
|
||||
* in sysfs.
|
||||
*
|
||||
* Note: You probably want to use root_device_register().
|
||||
*/
|
||||
struct device *__root_device_register(const char *name, struct module *owner)
|
||||
{
|
||||
struct root_device *root;
|
||||
int err = -ENOMEM;
|
||||
|
||||
root = kzalloc(sizeof(struct root_device), GFP_KERNEL);
|
||||
if (!root)
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = dev_set_name(&root->dev, name);
|
||||
if (err) {
|
||||
kfree(root);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
root->dev.release = root_device_release;
|
||||
|
||||
err = device_register(&root->dev);
|
||||
if (err) {
|
||||
put_device(&root->dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULE /* gotta find a "cleaner" way to do this */
|
||||
if (owner) {
|
||||
struct module_kobject *mk = &owner->mkobj;
|
||||
|
||||
err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module");
|
||||
if (err) {
|
||||
device_unregister(&root->dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
root->owner = owner;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &root->dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__root_device_register);
|
||||
|
||||
/**
|
||||
* root_device_unregister - unregister and free a root device
|
||||
* @root: device going away.
|
||||
*
|
||||
* This function unregisters and cleans up a device that was created by
|
||||
* root_device_register().
|
||||
*/
|
||||
void root_device_unregister(struct device *dev)
|
||||
{
|
||||
struct root_device *root = to_root_device(dev);
|
||||
|
||||
if (root->owner)
|
||||
sysfs_remove_link(&root->dev.kobj, "module");
|
||||
|
||||
device_unregister(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(root_device_unregister);
|
||||
|
||||
|
||||
static void device_create_release(struct device *dev)
|
||||
{
|
||||
|
@ -482,6 +482,17 @@ extern struct device *device_find_child(struct device *dev, void *data,
|
||||
extern int device_rename(struct device *dev, char *new_name);
|
||||
extern int device_move(struct device *dev, struct device *new_parent);
|
||||
|
||||
/*
|
||||
* Root device objects for grouping under /sys/devices
|
||||
*/
|
||||
extern struct device *__root_device_register(const char *name,
|
||||
struct module *owner);
|
||||
static inline struct device *root_device_register(const char *name)
|
||||
{
|
||||
return __root_device_register(name, THIS_MODULE);
|
||||
}
|
||||
extern void root_device_unregister(struct device *root);
|
||||
|
||||
/*
|
||||
* Manual binding of a device to driver. See drivers/base/bus.c
|
||||
* for information on use.
|
||||
|
Loading…
Reference in New Issue
Block a user