Commit c205ef48 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Driver core: create devices/virtual/ tree

This change creates a devices/virtual/CLASS_NAME tree for struct devices
that belong to a class, yet do not have a "real" struct device for a
parent.  It automatically creates the directories on the fly as needed.


Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a2de48ca
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "base.h" #include "base.h"
extern struct subsystem devices_subsys;
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj) #define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
...@@ -878,7 +880,22 @@ void class_interface_unregister(struct class_interface *class_intf) ...@@ -878,7 +880,22 @@ void class_interface_unregister(struct class_interface *class_intf)
class_put(parent); class_put(parent);
} }
int virtual_device_parent(struct device *dev)
{
if (!dev->class)
return -ENODEV;
if (!dev->class->virtual_dir) {
static struct kobject *virtual_dir = NULL;
if (!virtual_dir)
virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
}
dev->kobj.parent = dev->class->virtual_dir;
return 0;
}
int __init classes_init(void) int __init classes_init(void)
{ {
......
...@@ -378,6 +378,13 @@ int device_add(struct device *dev) ...@@ -378,6 +378,13 @@ int device_add(struct device *dev)
if (!dev || !strlen(dev->bus_id)) if (!dev || !strlen(dev->bus_id))
goto Error; goto Error;
/* if this is a class device, and has no parent, create one */
if ((dev->class) && (dev->parent == NULL)) {
error = virtual_device_parent(dev);
if (error)
goto Error;
}
parent = get_device(dev->parent); parent = get_device(dev->parent);
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
......
...@@ -149,6 +149,8 @@ struct class { ...@@ -149,6 +149,8 @@ struct class {
struct list_head interfaces; struct list_head interfaces;
struct semaphore sem; /* locks both the children and interfaces lists */ struct semaphore sem; /* locks both the children and interfaces lists */
struct kobject *virtual_dir;
struct class_attribute * class_attrs; struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs; struct class_device_attribute * class_dev_attrs;
struct device_attribute * dev_attrs; struct device_attribute * dev_attrs;
...@@ -291,7 +293,6 @@ extern struct class_device *class_device_create(struct class *cls, ...@@ -291,7 +293,6 @@ extern struct class_device *class_device_create(struct class *cls,
__attribute__((format(printf,5,6))); __attribute__((format(printf,5,6)));
extern void class_device_destroy(struct class *cls, dev_t devt); extern void class_device_destroy(struct class *cls, dev_t devt);
/* interface for exporting device attributes */ /* interface for exporting device attributes */
struct device_attribute { struct device_attribute {
struct attribute attr; struct attribute attr;
...@@ -400,6 +401,8 @@ extern struct device *device_create(struct class *cls, struct device *parent, ...@@ -400,6 +401,8 @@ extern struct device *device_create(struct class *cls, struct device *parent,
__attribute__((format(printf,4,5))); __attribute__((format(printf,4,5)));
extern void device_destroy(struct class *cls, dev_t devt); extern void device_destroy(struct class *cls, dev_t devt);
extern int virtual_device_parent(struct device *dev);
/* /*
* Platform "fixup" functions - allow the platform to have their say * Platform "fixup" functions - allow the platform to have their say
* about devices and actions that the general device layer doesn't * about devices and actions that the general device layer doesn't
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment