X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fbase%2Fclass.c;h=96def1ddba194b50347b171f221fbdfadbd896f5;hb=58a3bb59973e33a428d72fa530a3d1d81feb0e8f;hp=0ff267a248dba8ff5e215a380a54ea0f4221c7ce;hpb=65740356ccfa66703e7e0d47fbe372ba5193916b;p=pandora-kernel.git diff --git a/drivers/base/class.c b/drivers/base/class.c index 0ff267a248db..96def1ddba19 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -163,6 +163,8 @@ int class_register(struct class * cls) void class_unregister(struct class * cls) { pr_debug("device class '%s': unregistering\n", cls->name); + if (cls->virtual_dir) + kobject_unregister(cls->virtual_dir); remove_class_attrs(cls); subsystem_unregister(&cls->subsys); } @@ -352,6 +354,96 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj) return class_dev->class->name; } +#ifdef CONFIG_SYSFS_DEPRECATED +char *make_class_name(const char *name, struct kobject *kobj) +{ + char *class_name; + int size; + + size = strlen(name) + strlen(kobject_name(kobj)) + 2; + + class_name = kmalloc(size, GFP_KERNEL); + if (!class_name) + return NULL; + + strcpy(class_name, name); + strcat(class_name, ":"); + strcat(class_name, kobject_name(kobj)); + return class_name; +} + +static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index, + char *buffer, int buffer_size, + int *cur_len, + struct class_device *class_dev) +{ + struct device *dev = class_dev->dev; + char *path; + + if (!dev) + return 0; + + /* add device, backing this class device (deprecated) */ + path = kobject_get_path(&dev->kobj, GFP_KERNEL); + + add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size, + cur_len, "PHYSDEVPATH=%s", path); + kfree(path); + + if (dev->bus) + add_uevent_var(envp, num_envp, cur_index, + buffer, buffer_size, cur_len, + "PHYSDEVBUS=%s", dev->bus->name); + + if (dev->driver) + add_uevent_var(envp, num_envp, cur_index, + buffer, buffer_size, cur_len, + "PHYSDEVDRIVER=%s", dev->driver->name); + return 0; +} + +static int make_deprecated_class_device_links(struct class_device *class_dev) +{ + char *class_name; + int error; + + if (!class_dev->dev) + return 0; + + class_name = make_class_name(class_dev->class->name, &class_dev->kobj); + if (class_name) + error = sysfs_create_link(&class_dev->dev->kobj, + &class_dev->kobj, class_name); + else + error = -ENOMEM; + kfree(class_name); + return error; +} + +static void remove_deprecated_class_device_links(struct class_device *class_dev) +{ + char *class_name; + + if (!class_dev->dev) + return; + + class_name = make_class_name(class_dev->class->name, &class_dev->kobj); + if (class_name) + sysfs_remove_link(&class_dev->dev->kobj, class_name); + kfree(class_name); +} +#else +static inline int deprecated_class_uevent(char **envp, int num_envp, + int *cur_index, char *buffer, + int buffer_size, int *cur_len, + struct class_device *class_dev) +{ return 0; } +static inline int make_deprecated_class_device_links(struct class_device *cd) +{ return 0; } +static void remove_deprecated_class_device_links(struct class_device *cd) +{ } +#endif + static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, int num_envp, char *buffer, int buffer_size) { @@ -362,25 +454,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); - if (class_dev->dev) { - /* add device, backing this class device (deprecated) */ - struct device *dev = class_dev->dev; - char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "PHYSDEVPATH=%s", path); - kfree(path); - - if (dev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); - - if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); - } + deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size, + &length, class_dev); if (MAJOR(class_dev->devt)) { add_uevent_var(envp, num_envp, &i, @@ -506,29 +581,11 @@ void class_device_initialize(struct class_device *class_dev) INIT_LIST_HEAD(&class_dev->node); } -char *make_class_name(const char *name, struct kobject *kobj) -{ - char *class_name; - int size; - - size = strlen(name) + strlen(kobject_name(kobj)) + 2; - - class_name = kmalloc(size, GFP_KERNEL); - if (!class_name) - return ERR_PTR(-ENOMEM); - - strcpy(class_name, name); - strcat(class_name, ":"); - strcat(class_name, kobject_name(kobj)); - return class_name; -} - int class_device_add(struct class_device *class_dev) { struct class *parent_class = NULL; struct class_device *parent_class_dev = NULL; struct class_interface *class_intf; - char *class_name = NULL; int error = -EINVAL; class_dev = class_device_get(class_dev); @@ -599,19 +656,17 @@ int class_device_add(struct class_device *class_dev) goto out5; if (class_dev->dev) { - class_name = make_class_name(class_dev->class->name, - &class_dev->kobj); error = sysfs_create_link(&class_dev->kobj, &class_dev->dev->kobj, "device"); if (error) goto out6; - error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, - class_name); - if (error) - goto out7; } error = class_device_add_groups(class_dev); + if (error) + goto out7; + + error = make_deprecated_class_device_links(class_dev); if (error) goto out8; @@ -629,8 +684,7 @@ int class_device_add(struct class_device *class_dev) goto out1; out8: - if (class_dev->dev) - sysfs_remove_link(&class_dev->kobj, class_name); + class_device_remove_groups(class_dev); out7: if (class_dev->dev) sysfs_remove_link(&class_dev->kobj, "device"); @@ -649,7 +703,6 @@ int class_device_add(struct class_device *class_dev) class_put(parent_class); out1: class_device_put(class_dev); - kfree(class_name); return error; } @@ -726,7 +779,6 @@ void class_device_del(struct class_device *class_dev) struct class *parent_class = class_dev->class; struct class_device *parent_device = class_dev->parent; struct class_interface *class_intf; - char *class_name = NULL; if (parent_class) { down(&parent_class->sem); @@ -738,10 +790,8 @@ void class_device_del(struct class_device *class_dev) } if (class_dev->dev) { - class_name = make_class_name(class_dev->class->name, - &class_dev->kobj); + remove_deprecated_class_device_links(class_dev); sysfs_remove_link(&class_dev->kobj, "device"); - sysfs_remove_link(&class_dev->dev->kobj, class_name); } sysfs_remove_link(&class_dev->kobj, "subsystem"); class_device_remove_file(class_dev, &class_dev->uevent_attr); @@ -755,7 +805,6 @@ void class_device_del(struct class_device *class_dev) class_device_put(parent_device); class_put(parent_class); - kfree(class_name); } void class_device_unregister(struct class_device *class_dev) @@ -804,21 +853,28 @@ int class_device_rename(struct class_device *class_dev, char *new_name) pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if (class_dev->dev) old_class_name = make_class_name(class_dev->class->name, &class_dev->kobj); +#endif strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if (class_dev->dev) { new_class_name = make_class_name(class_dev->class->name, &class_dev->kobj); - sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, - new_class_name); - sysfs_remove_link(&class_dev->dev->kobj, old_class_name); + if (new_class_name) + sysfs_create_link(&class_dev->dev->kobj, + &class_dev->kobj, new_class_name); + if (old_class_name) + sysfs_remove_link(&class_dev->dev->kobj, + old_class_name); } +#endif class_device_put(class_dev); kfree(old_class_name); @@ -893,23 +949,6 @@ void class_interface_unregister(struct class_interface *class_intf) 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 retval;