aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/base.h27
-rw-r--r--drivers/base/class.c87
-rw-r--r--drivers/base/core.c57
-rw-r--r--include/linux/device.h7
4 files changed, 107 insertions, 71 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 2c9ae43e2219..0ec372a67762 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -36,6 +36,33 @@ struct driver_private {
36}; 36};
37#define to_driver(obj) container_of(obj, struct driver_private, kobj) 37#define to_driver(obj) container_of(obj, struct driver_private, kobj)
38 38
39
40/**
41 * struct class_private - structure to hold the private to the driver core portions of the class structure.
42 *
43 * @subsys - the struct kset that defines this class. This is the main kobject
44 * @children - list of class_devices associated with this class
45 * @devices - list of devices associated with this class
46 * @interfaces - list of class_interfaces associated with this class
47 * @class_dirs -
48 * @sem - semaphore to protect the children, devices, and interfaces lists.
49 * @class - pointer back to the struct class that this structure is associated
50 * with.
51 *
52 * This structure is the one that is the actual kobject allowing struct
53 * class to be statically allocated safely. Nothing outside of the driver
54 * core should ever touch these fields.
55 */
56struct class_private {
57 struct kset subsys;
58 struct list_head devices;
59 struct list_head interfaces;
60 struct kset class_dirs;
61 struct semaphore sem;
62 struct class *class;
63};
64#define to_class(obj) container_of(obj, struct class_private, subsys.kobj)
65
39/* initialisation functions */ 66/* initialisation functions */
40extern int devices_init(void); 67extern int devices_init(void);
41extern int buses_init(void); 68extern int buses_init(void);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 3918d0e432d4..06f09c929a91 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -21,17 +21,16 @@
21#include "base.h" 21#include "base.h"
22 22
23#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) 23#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
24#define to_class(obj) container_of(obj, struct class, subsys.kobj)
25 24
26static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, 25static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
27 char *buf) 26 char *buf)
28{ 27{
29 struct class_attribute *class_attr = to_class_attr(attr); 28 struct class_attribute *class_attr = to_class_attr(attr);
30 struct class *dc = to_class(kobj); 29 struct class_private *cp = to_class(kobj);
31 ssize_t ret = -EIO; 30 ssize_t ret = -EIO;
32 31
33 if (class_attr->show) 32 if (class_attr->show)
34 ret = class_attr->show(dc, buf); 33 ret = class_attr->show(cp->class, buf);
35 return ret; 34 return ret;
36} 35}
37 36
@@ -39,17 +38,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
39 const char *buf, size_t count) 38 const char *buf, size_t count)
40{ 39{
41 struct class_attribute *class_attr = to_class_attr(attr); 40 struct class_attribute *class_attr = to_class_attr(attr);
42 struct class *dc = to_class(kobj); 41 struct class_private *cp = to_class(kobj);
43 ssize_t ret = -EIO; 42 ssize_t ret = -EIO;
44 43
45 if (class_attr->store) 44 if (class_attr->store)
46 ret = class_attr->store(dc, buf, count); 45 ret = class_attr->store(cp->class, buf, count);
47 return ret; 46 return ret;
48} 47}
49 48
50static void class_release(struct kobject *kobj) 49static void class_release(struct kobject *kobj)
51{ 50{
52 struct class *class = to_class(kobj); 51 struct class_private *cp = to_class(kobj);
52 struct class *class = cp->class;
53 53
54 pr_debug("class '%s': release.\n", class->name); 54 pr_debug("class '%s': release.\n", class->name);
55 55
@@ -78,7 +78,7 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
78{ 78{
79 int error; 79 int error;
80 if (cls) 80 if (cls)
81 error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); 81 error = sysfs_create_file(&cls->p->subsys.kobj, &attr->attr);
82 else 82 else
83 error = -EINVAL; 83 error = -EINVAL;
84 return error; 84 return error;
@@ -87,21 +87,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
87void class_remove_file(struct class *cls, const struct class_attribute *attr) 87void class_remove_file(struct class *cls, const struct class_attribute *attr)
88{ 88{
89 if (cls) 89 if (cls)
90 sysfs_remove_file(&cls->subsys.kobj, &attr->attr); 90 sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr);
91} 91}
92 92
93static struct class *class_get(struct class *cls) 93static struct class *class_get(struct class *cls)
94{ 94{
95 if (cls) 95 if (cls)
96 return container_of(kset_get(&cls->subsys), 96 kset_get(&cls->p->subsys);
97 struct class, subsys); 97 return cls;
98 return NULL;
99} 98}
100 99
101static void class_put(struct class *cls) 100static void class_put(struct class *cls)
102{ 101{
103 if (cls) 102 if (cls)
104 kset_put(&cls->subsys); 103 kset_put(&cls->p->subsys);
105} 104}
106 105
107static int add_class_attrs(struct class *cls) 106static int add_class_attrs(struct class *cls)
@@ -136,17 +135,23 @@ static void remove_class_attrs(struct class *cls)
136 135
137int class_register(struct class *cls) 136int class_register(struct class *cls)
138{ 137{
138 struct class_private *cp;
139 int error; 139 int error;
140 140
141 pr_debug("device class '%s': registering\n", cls->name); 141 pr_debug("device class '%s': registering\n", cls->name);
142 142
143 INIT_LIST_HEAD(&cls->devices); 143 cp = kzalloc(sizeof(*cp), GFP_KERNEL);
144 INIT_LIST_HEAD(&cls->interfaces); 144 if (!cp)
145 kset_init(&cls->class_dirs); 145 return -ENOMEM;
146 init_MUTEX(&cls->sem); 146 INIT_LIST_HEAD(&cp->devices);
147 error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name); 147 INIT_LIST_HEAD(&cp->interfaces);
148 if (error) 148 kset_init(&cp->class_dirs);
149 init_MUTEX(&cp->sem);
150 error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
151 if (error) {
152 kfree(cp);
149 return error; 153 return error;
154 }
150 155
151 /* set the default /sys/dev directory for devices of this class */ 156 /* set the default /sys/dev directory for devices of this class */
152 if (!cls->dev_kobj) 157 if (!cls->dev_kobj)
@@ -155,17 +160,21 @@ int class_register(struct class *cls)
155#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) 160#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
156 /* let the block class directory show up in the root of sysfs */ 161 /* let the block class directory show up in the root of sysfs */
157 if (cls != &block_class) 162 if (cls != &block_class)
158 cls->subsys.kobj.kset = class_kset; 163 cp->subsys.kobj.kset = class_kset;
159#else 164#else
160 cls->subsys.kobj.kset = class_kset; 165 cp->subsys.kobj.kset = class_kset;
161#endif 166#endif
162 cls->subsys.kobj.ktype = &class_ktype; 167 cp->subsys.kobj.ktype = &class_ktype;
168 cp->class = cls;
169 cls->p = cp;
163 170
164 error = kset_register(&cls->subsys); 171 error = kset_register(&cp->subsys);
165 if (!error) { 172 if (error) {
166 error = add_class_attrs(class_get(cls)); 173 kfree(cp);
167 class_put(cls); 174 return error;
168 } 175 }
176 error = add_class_attrs(class_get(cls));
177 class_put(cls);
169 return error; 178 return error;
170} 179}
171 180
@@ -173,7 +182,7 @@ void class_unregister(struct class *cls)
173{ 182{
174 pr_debug("device class '%s': unregistering\n", cls->name); 183 pr_debug("device class '%s': unregistering\n", cls->name);
175 remove_class_attrs(cls); 184 remove_class_attrs(cls);
176 kset_unregister(&cls->subsys); 185 kset_unregister(&cls->p->subsys);
177} 186}
178 187
179static void class_create_release(struct class *cls) 188static void class_create_release(struct class *cls)
@@ -280,8 +289,8 @@ int class_for_each_device(struct class *class, struct device *start,
280 289
281 if (!class) 290 if (!class)
282 return -EINVAL; 291 return -EINVAL;
283 down(&class->sem); 292 down(&class->p->sem);
284 list_for_each_entry(dev, &class->devices, node) { 293 list_for_each_entry(dev, &class->p->devices, node) {
285 if (start) { 294 if (start) {
286 if (start == dev) 295 if (start == dev)
287 start = NULL; 296 start = NULL;
@@ -293,7 +302,7 @@ int class_for_each_device(struct class *class, struct device *start,
293 if (error) 302 if (error)
294 break; 303 break;
295 } 304 }
296 up(&class->sem); 305 up(&class->p->sem);
297 306
298 return error; 307 return error;
299} 308}
@@ -330,8 +339,8 @@ struct device *class_find_device(struct class *class, struct device *start,
330 if (!class) 339 if (!class)
331 return NULL; 340 return NULL;
332 341
333 down(&class->sem); 342 down(&class->p->sem);
334 list_for_each_entry(dev, &class->devices, node) { 343 list_for_each_entry(dev, &class->p->devices, node) {
335 if (start) { 344 if (start) {
336 if (start == dev) 345 if (start == dev)
337 start = NULL; 346 start = NULL;
@@ -344,7 +353,7 @@ struct device *class_find_device(struct class *class, struct device *start,
344 } else 353 } else
345 put_device(dev); 354 put_device(dev);
346 } 355 }
347 up(&class->sem); 356 up(&class->p->sem);
348 357
349 return found ? dev : NULL; 358 return found ? dev : NULL;
350} 359}
@@ -362,13 +371,13 @@ int class_interface_register(struct class_interface *class_intf)
362 if (!parent) 371 if (!parent)
363 return -EINVAL; 372 return -EINVAL;
364 373
365 down(&parent->sem); 374 down(&parent->p->sem);
366 list_add_tail(&class_intf->node, &parent->interfaces); 375 list_add_tail(&class_intf->node, &parent->p->interfaces);
367 if (class_intf->add_dev) { 376 if (class_intf->add_dev) {
368 list_for_each_entry(dev, &parent->devices, node) 377 list_for_each_entry(dev, &parent->p->devices, node)
369 class_intf->add_dev(dev, class_intf); 378 class_intf->add_dev(dev, class_intf);
370 } 379 }
371 up(&parent->sem); 380 up(&parent->p->sem);
372 381
373 return 0; 382 return 0;
374} 383}
@@ -381,13 +390,13 @@ void class_interface_unregister(struct class_interface *class_intf)
381 if (!parent) 390 if (!parent)
382 return; 391 return;
383 392
384 down(&parent->sem); 393 down(&parent->p->sem);
385 list_del_init(&class_intf->node); 394 list_del_init(&class_intf->node);
386 if (class_intf->remove_dev) { 395 if (class_intf->remove_dev) {
387 list_for_each_entry(dev, &parent->devices, node) 396 list_for_each_entry(dev, &parent->p->devices, node)
388 class_intf->remove_dev(dev, class_intf); 397 class_intf->remove_dev(dev, class_intf);
389 } 398 }
390 up(&parent->sem); 399 up(&parent->p->sem);
391 400
392 class_put(parent); 401 class_put(parent);
393} 402}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 9f05de6f80b5..64c150b5a883 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -551,7 +551,7 @@ static struct kobject *get_device_parent(struct device *dev,
551{ 551{
552 /* class devices without a parent live in /sys/class/<classname>/ */ 552 /* class devices without a parent live in /sys/class/<classname>/ */
553 if (dev->class && (!parent || parent->class != dev->class)) 553 if (dev->class && (!parent || parent->class != dev->class))
554 return &dev->class->subsys.kobj; 554 return &dev->class->p->subsys.kobj;
555 /* all other devices keep their parent */ 555 /* all other devices keep their parent */
556 else if (parent) 556 else if (parent)
557 return &parent->kobj; 557 return &parent->kobj;
@@ -597,13 +597,13 @@ static struct kobject *get_device_parent(struct device *dev,
597 parent_kobj = &parent->kobj; 597 parent_kobj = &parent->kobj;
598 598
599 /* find our class-directory at the parent and reference it */ 599 /* find our class-directory at the parent and reference it */
600 spin_lock(&dev->class->class_dirs.list_lock); 600 spin_lock(&dev->class->p->class_dirs.list_lock);
601 list_for_each_entry(k, &dev->class->class_dirs.list, entry) 601 list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
602 if (k->parent == parent_kobj) { 602 if (k->parent == parent_kobj) {
603 kobj = kobject_get(k); 603 kobj = kobject_get(k);
604 break; 604 break;
605 } 605 }
606 spin_unlock(&dev->class->class_dirs.list_lock); 606 spin_unlock(&dev->class->p->class_dirs.list_lock);
607 if (kobj) 607 if (kobj)
608 return kobj; 608 return kobj;
609 609
@@ -611,7 +611,7 @@ static struct kobject *get_device_parent(struct device *dev,
611 k = kobject_create(); 611 k = kobject_create();
612 if (!k) 612 if (!k)
613 return NULL; 613 return NULL;
614 k->kset = &dev->class->class_dirs; 614 k->kset = &dev->class->p->class_dirs;
615 retval = kobject_add(k, parent_kobj, "%s", dev->class->name); 615 retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
616 if (retval < 0) { 616 if (retval < 0) {
617 kobject_put(k); 617 kobject_put(k);
@@ -630,7 +630,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
630{ 630{
631 /* see if we live in a "glue" directory */ 631 /* see if we live in a "glue" directory */
632 if (!glue_dir || !dev->class || 632 if (!glue_dir || !dev->class ||
633 glue_dir->kset != &dev->class->class_dirs) 633 glue_dir->kset != &dev->class->p->class_dirs)
634 return; 634 return;
635 635
636 kobject_put(glue_dir); 636 kobject_put(glue_dir);
@@ -657,17 +657,17 @@ static int device_add_class_symlinks(struct device *dev)
657 if (!dev->class) 657 if (!dev->class)
658 return 0; 658 return 0;
659 659
660 error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, 660 error = sysfs_create_link(&dev->kobj, &dev->class->p->subsys.kobj,
661 "subsystem"); 661 "subsystem");
662 if (error) 662 if (error)
663 goto out; 663 goto out;
664 664
665#ifdef CONFIG_SYSFS_DEPRECATED 665#ifdef CONFIG_SYSFS_DEPRECATED
666 /* stacked class devices need a symlink in the class directory */ 666 /* stacked class devices need a symlink in the class directory */
667 if (dev->kobj.parent != &dev->class->subsys.kobj && 667 if (dev->kobj.parent != &dev->class->p->subsys.kobj &&
668 device_is_not_partition(dev)) { 668 device_is_not_partition(dev)) {
669 error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, 669 error = sysfs_create_link(&dev->class->p->subsys.kobj,
670 dev->bus_id); 670 &dev->kobj, dev->bus_id);
671 if (error) 671 if (error)
672 goto out_subsys; 672 goto out_subsys;
673 } 673 }
@@ -704,12 +704,12 @@ out_device:
704 if (dev->parent && device_is_not_partition(dev)) 704 if (dev->parent && device_is_not_partition(dev))
705 sysfs_remove_link(&dev->kobj, "device"); 705 sysfs_remove_link(&dev->kobj, "device");
706out_busid: 706out_busid:
707 if (dev->kobj.parent != &dev->class->subsys.kobj && 707 if (dev->kobj.parent != &dev->class->p->subsys.kobj &&
708 device_is_not_partition(dev)) 708 device_is_not_partition(dev))
709 sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); 709 sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id);
710#else 710#else
711 /* link in the class directory pointing to the device */ 711 /* link in the class directory pointing to the device */
712 error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, 712 error = sysfs_create_link(&dev->class->p->subsys.kobj, &dev->kobj,
713 dev->bus_id); 713 dev->bus_id);
714 if (error) 714 if (error)
715 goto out_subsys; 715 goto out_subsys;
@@ -723,7 +723,7 @@ out_busid:
723 return 0; 723 return 0;
724 724
725out_busid: 725out_busid:
726 sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); 726 sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id);
727#endif 727#endif
728 728
729out_subsys: 729out_subsys:
@@ -749,14 +749,14 @@ static void device_remove_class_symlinks(struct device *dev)
749 sysfs_remove_link(&dev->kobj, "device"); 749 sysfs_remove_link(&dev->kobj, "device");
750 } 750 }
751 751
752 if (dev->kobj.parent != &dev->class->subsys.kobj && 752 if (dev->kobj.parent != &dev->class->p->subsys.kobj &&
753 device_is_not_partition(dev)) 753 device_is_not_partition(dev))
754 sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); 754 sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id);
755#else 755#else
756 if (dev->parent && device_is_not_partition(dev)) 756 if (dev->parent && device_is_not_partition(dev))
757 sysfs_remove_link(&dev->kobj, "device"); 757 sysfs_remove_link(&dev->kobj, "device");
758 758
759 sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); 759 sysfs_remove_link(&dev->class->p->subsys.kobj, dev->bus_id);
760#endif 760#endif
761 761
762 sysfs_remove_link(&dev->kobj, "subsystem"); 762 sysfs_remove_link(&dev->kobj, "subsystem");
@@ -904,15 +904,16 @@ int device_add(struct device *dev)
904 klist_add_tail(&dev->knode_parent, &parent->klist_children); 904 klist_add_tail(&dev->knode_parent, &parent->klist_children);
905 905
906 if (dev->class) { 906 if (dev->class) {
907 down(&dev->class->sem); 907 down(&dev->class->p->sem);
908 /* tie the class to the device */ 908 /* tie the class to the device */
909 list_add_tail(&dev->node, &dev->class->devices); 909 list_add_tail(&dev->node, &dev->class->p->devices);
910 910
911 /* notify any interfaces that the device is here */ 911 /* notify any interfaces that the device is here */
912 list_for_each_entry(class_intf, &dev->class->interfaces, node) 912 list_for_each_entry(class_intf, &dev->class->p->interfaces,
913 node)
913 if (class_intf->add_dev) 914 if (class_intf->add_dev)
914 class_intf->add_dev(dev, class_intf); 915 class_intf->add_dev(dev, class_intf);
915 up(&dev->class->sem); 916 up(&dev->class->p->sem);
916 } 917 }
917 Done: 918 Done:
918 put_device(dev); 919 put_device(dev);
@@ -1013,14 +1014,15 @@ void device_del(struct device *dev)
1013 if (dev->class) { 1014 if (dev->class) {
1014 device_remove_class_symlinks(dev); 1015 device_remove_class_symlinks(dev);
1015 1016
1016 down(&dev->class->sem); 1017 down(&dev->class->p->sem);
1017 /* notify any interfaces that the device is now gone */ 1018 /* notify any interfaces that the device is now gone */
1018 list_for_each_entry(class_intf, &dev->class->interfaces, node) 1019 list_for_each_entry(class_intf, &dev->class->p->interfaces,
1020 node)
1019 if (class_intf->remove_dev) 1021 if (class_intf->remove_dev)
1020 class_intf->remove_dev(dev, class_intf); 1022 class_intf->remove_dev(dev, class_intf);
1021 /* remove the device from the class list */ 1023 /* remove the device from the class list */
1022 list_del_init(&dev->node); 1024 list_del_init(&dev->node);
1023 up(&dev->class->sem); 1025 up(&dev->class->p->sem);
1024 } 1026 }
1025 device_remove_file(dev, &uevent_attr); 1027 device_remove_file(dev, &uevent_attr);
1026 device_remove_attrs(dev); 1028 device_remove_attrs(dev);
@@ -1348,11 +1350,12 @@ int device_rename(struct device *dev, char *new_name)
1348 } 1350 }
1349#else 1351#else
1350 if (dev->class) { 1352 if (dev->class) {
1351 error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, 1353 error = sysfs_create_link(&dev->class->p->subsys.kobj,
1352 dev->bus_id); 1354 &dev->kobj, dev->bus_id);
1353 if (error) 1355 if (error)
1354 goto out; 1356 goto out;
1355 sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); 1357 sysfs_remove_link(&dev->class->p->subsys.kobj,
1358 old_device_name);
1356 } 1359 }
1357#endif 1360#endif
1358 1361
diff --git a/include/linux/device.h b/include/linux/device.h
index c1f72984875f..b0556082179b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -35,6 +35,7 @@ struct device;
35struct device_driver; 35struct device_driver;
36struct driver_private; 36struct driver_private;
37struct class; 37struct class;
38struct class_private;
38struct bus_type; 39struct bus_type;
39struct bus_type_private; 40struct bus_type_private;
40 41
@@ -186,11 +187,6 @@ struct class {
186 const char *name; 187 const char *name;
187 struct module *owner; 188 struct module *owner;
188 189
189 struct kset subsys;
190 struct list_head devices;
191 struct list_head interfaces;
192 struct kset class_dirs;
193 struct semaphore sem; /* locks children, devices, interfaces */
194 struct class_attribute *class_attrs; 190 struct class_attribute *class_attrs;
195 struct device_attribute *dev_attrs; 191 struct device_attribute *dev_attrs;
196 struct kobject *dev_kobj; 192 struct kobject *dev_kobj;
@@ -204,6 +200,7 @@ struct class {
204 int (*resume)(struct device *dev); 200 int (*resume)(struct device *dev);
205 201
206 struct pm_ops *pm; 202 struct pm_ops *pm;
203 struct class_private *p;
207}; 204};
208 205
209extern struct kobject *sysfs_dev_block_kobj; 206extern struct kobject *sysfs_dev_block_kobj;