diff options
Diffstat (limited to 'drivers/base/core.c')
| -rw-r--r-- | drivers/base/core.c | 77 | 
1 files changed, 63 insertions, 14 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 356dd011b8f..f0699918e2f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -131,9 +131,21 @@ static void device_release(struct kobject *kobj)  	kfree(p);  } +static const void *device_namespace(struct kobject *kobj) +{ +	struct device *dev = to_dev(kobj); +	const void *ns = NULL; + +	if (dev->class && dev->class->ns_type) +		ns = dev->class->namespace(dev); + +	return ns; +} +  static struct kobj_type device_ktype = {  	.release	= device_release,  	.sysfs_ops	= &dev_sysfs_ops, +	.namespace	= device_namespace,  }; @@ -595,11 +607,59 @@ static struct kobject *virtual_device_parent(struct device *dev)  	return virtual_dir;  } -static struct kobject *get_device_parent(struct device *dev, -					 struct device *parent) +struct class_dir { +	struct kobject kobj; +	struct class *class; +}; + +#define to_class_dir(obj) container_of(obj, struct class_dir, kobj) + +static void class_dir_release(struct kobject *kobj) +{ +	struct class_dir *dir = to_class_dir(kobj); +	kfree(dir); +} + +static const +struct kobj_ns_type_operations *class_dir_child_ns_type(struct kobject *kobj)  { +	struct class_dir *dir = to_class_dir(kobj); +	return dir->class->ns_type; +} + +static struct kobj_type class_dir_ktype = { +	.release	= class_dir_release, +	.sysfs_ops	= &kobj_sysfs_ops, +	.child_ns_type	= class_dir_child_ns_type +}; + +static struct kobject * +class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) +{ +	struct class_dir *dir;  	int retval; +	dir = kzalloc(sizeof(*dir), GFP_KERNEL); +	if (!dir) +		return NULL; + +	dir->class = class; +	kobject_init(&dir->kobj, &class_dir_ktype); + +	dir->kobj.kset = &class->p->class_dirs; + +	retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); +	if (retval < 0) { +		kobject_put(&dir->kobj); +		return NULL; +	} +	return &dir->kobj; +} + + +static struct kobject *get_device_parent(struct device *dev, +					 struct device *parent) +{  	if (dev->class) {  		static DEFINE_MUTEX(gdp_mutex);  		struct kobject *kobj = NULL; @@ -634,18 +694,7 @@ static struct kobject *get_device_parent(struct device *dev,  		}  		/* or create a new class-directory at the parent device */ -		k = kobject_create(); -		if (!k) { -			mutex_unlock(&gdp_mutex); -			return NULL; -		} -		k->kset = &dev->class->p->class_dirs; -		retval = kobject_add(k, parent_kobj, "%s", dev->class->name); -		if (retval < 0) { -			mutex_unlock(&gdp_mutex); -			kobject_put(k); -			return NULL; -		} +		k = class_dir_create_and_add(dev->class, parent_kobj);  		/* do not emit an uevent for this simple "glue" directory */  		mutex_unlock(&gdp_mutex);  		return k;  |