aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r--drivers/base/class.c194
1 files changed, 180 insertions, 14 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d2a2f8f2b4ed..479c12570881 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/kdev_t.h> 18#include <linux/kdev_t.h>
19#include <linux/err.h>
19#include "base.h" 20#include "base.h"
20 21
21#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) 22#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -26,7 +27,7 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
26{ 27{
27 struct class_attribute * class_attr = to_class_attr(attr); 28 struct class_attribute * class_attr = to_class_attr(attr);
28 struct class * dc = to_class(kobj); 29 struct class * dc = to_class(kobj);
29 ssize_t ret = 0; 30 ssize_t ret = -EIO;
30 31
31 if (class_attr->show) 32 if (class_attr->show)
32 ret = class_attr->show(dc, buf); 33 ret = class_attr->show(dc, buf);
@@ -39,7 +40,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
39{ 40{
40 struct class_attribute * class_attr = to_class_attr(attr); 41 struct class_attribute * class_attr = to_class_attr(attr);
41 struct class * dc = to_class(kobj); 42 struct class * dc = to_class(kobj);
42 ssize_t ret = 0; 43 ssize_t ret = -EIO;
43 44
44 if (class_attr->store) 45 if (class_attr->store)
45 ret = class_attr->store(dc, buf, count); 46 ret = class_attr->store(dc, buf, count);
@@ -162,6 +163,69 @@ void class_unregister(struct class * cls)
162 subsystem_unregister(&cls->subsys); 163 subsystem_unregister(&cls->subsys);
163} 164}
164 165
166static void class_create_release(struct class *cls)
167{
168 kfree(cls);
169}
170
171static void class_device_create_release(struct class_device *class_dev)
172{
173 kfree(class_dev);
174}
175
176/**
177 * class_create - create a struct class structure
178 * @owner: pointer to the module that is to "own" this struct class
179 * @name: pointer to a string for the name of this class.
180 *
181 * This is used to create a struct class pointer that can then be used
182 * in calls to class_device_create().
183 *
184 * Note, the pointer created here is to be destroyed when finished by
185 * making a call to class_destroy().
186 */
187struct class *class_create(struct module *owner, char *name)
188{
189 struct class *cls;
190 int retval;
191
192 cls = kmalloc(sizeof(struct class), GFP_KERNEL);
193 if (!cls) {
194 retval = -ENOMEM;
195 goto error;
196 }
197 memset(cls, 0x00, sizeof(struct class));
198
199 cls->name = name;
200 cls->owner = owner;
201 cls->class_release = class_create_release;
202 cls->release = class_device_create_release;
203
204 retval = class_register(cls);
205 if (retval)
206 goto error;
207
208 return cls;
209
210error:
211 kfree(cls);
212 return ERR_PTR(retval);
213}
214
215/**
216 * class_destroy - destroys a struct class structure
217 * @cs: pointer to the struct class that is to be destroyed
218 *
219 * Note, the pointer to be destroyed must have been created with a call
220 * to class_create().
221 */
222void class_destroy(struct class *cls)
223{
224 if ((cls == NULL) || (IS_ERR(cls)))
225 return;
226
227 class_unregister(cls);
228}
165 229
166/* Class Device Stuff */ 230/* Class Device Stuff */
167 231
@@ -262,7 +326,7 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
262 return 0; 326 return 0;
263} 327}
264 328
265static char *class_hotplug_name(struct kset *kset, struct kobject *kobj) 329static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
266{ 330{
267 struct class_device *class_dev = to_class_dev(kobj); 331 struct class_device *class_dev = to_class_dev(kobj);
268 332
@@ -375,7 +439,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
375{ 439{
376 return print_dev_t(buf, class_dev->devt); 440 return print_dev_t(buf, class_dev->devt);
377} 441}
378static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
379 442
380void class_device_initialize(struct class_device *class_dev) 443void class_device_initialize(struct class_device *class_dev)
381{ 444{
@@ -412,7 +475,31 @@ int class_device_add(struct class_device *class_dev)
412 if ((error = kobject_add(&class_dev->kobj))) 475 if ((error = kobject_add(&class_dev->kobj)))
413 goto register_done; 476 goto register_done;
414 477
415 /* now take care of our own registration */ 478 /* add the needed attributes to this device */
479 if (MAJOR(class_dev->devt)) {
480 struct class_device_attribute *attr;
481 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
482 if (!attr) {
483 error = -ENOMEM;
484 kobject_del(&class_dev->kobj);
485 goto register_done;
486 }
487 memset(attr, sizeof(*attr), 0x00);
488 attr->attr.name = "dev";
489 attr->attr.mode = S_IRUGO;
490 attr->attr.owner = parent->owner;
491 attr->show = show_dev;
492 attr->store = NULL;
493 class_device_create_file(class_dev, attr);
494 class_dev->devt_attr = attr;
495 }
496
497 class_device_add_attrs(class_dev);
498 if (class_dev->dev)
499 sysfs_create_link(&class_dev->kobj,
500 &class_dev->dev->kobj, "device");
501
502 /* notify any interfaces this device is now here */
416 if (parent) { 503 if (parent) {
417 down(&parent->sem); 504 down(&parent->sem);
418 list_add_tail(&class_dev->node, &parent->children); 505 list_add_tail(&class_dev->node, &parent->children);
@@ -421,16 +508,8 @@ int class_device_add(struct class_device *class_dev)
421 class_intf->add(class_dev); 508 class_intf->add(class_dev);
422 up(&parent->sem); 509 up(&parent->sem);
423 } 510 }
424
425 if (MAJOR(class_dev->devt))
426 class_device_create_file(class_dev, &class_device_attr_dev);
427
428 class_device_add_attrs(class_dev);
429 if (class_dev->dev)
430 sysfs_create_link(&class_dev->kobj,
431 &class_dev->dev->kobj, "device");
432
433 kobject_hotplug(&class_dev->kobj, KOBJ_ADD); 511 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
512
434 register_done: 513 register_done:
435 if (error && parent) 514 if (error && parent)
436 class_put(parent); 515 class_put(parent);
@@ -444,6 +523,58 @@ int class_device_register(struct class_device *class_dev)
444 return class_device_add(class_dev); 523 return class_device_add(class_dev);
445} 524}
446 525
526/**
527 * class_device_create - creates a class device and registers it with sysfs
528 * @cs: pointer to the struct class that this device should be registered to.
529 * @dev: the dev_t for the char device to be added.
530 * @device: a pointer to a struct device that is assiociated with this class device.
531 * @fmt: string for the class device's name
532 *
533 * This function can be used by char device classes. A struct
534 * class_device will be created in sysfs, registered to the specified
535 * class. A "dev" file will be created, showing the dev_t for the
536 * device. The pointer to the struct class_device will be returned from
537 * the call. Any further sysfs files that might be required can be
538 * created using this pointer.
539 *
540 * Note: the struct class passed to this function must have previously
541 * been created with a call to class_create().
542 */
543struct class_device *class_device_create(struct class *cls, dev_t devt,
544 struct device *device, char *fmt, ...)
545{
546 va_list args;
547 struct class_device *class_dev = NULL;
548 int retval = -ENODEV;
549
550 if (cls == NULL || IS_ERR(cls))
551 goto error;
552
553 class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
554 if (!class_dev) {
555 retval = -ENOMEM;
556 goto error;
557 }
558 memset(class_dev, 0x00, sizeof(struct class_device));
559
560 class_dev->devt = devt;
561 class_dev->dev = device;
562 class_dev->class = cls;
563
564 va_start(args, fmt);
565 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
566 va_end(args);
567 retval = class_device_register(class_dev);
568 if (retval)
569 goto error;
570
571 return class_dev;
572
573error:
574 kfree(class_dev);
575 return ERR_PTR(retval);
576}
577
447void class_device_del(struct class_device *class_dev) 578void class_device_del(struct class_device *class_dev)
448{ 579{
449 struct class * parent = class_dev->class; 580 struct class * parent = class_dev->class;
@@ -460,6 +591,11 @@ void class_device_del(struct class_device *class_dev)
460 591
461 if (class_dev->dev) 592 if (class_dev->dev)
462 sysfs_remove_link(&class_dev->kobj, "device"); 593 sysfs_remove_link(&class_dev->kobj, "device");
594 if (class_dev->devt_attr) {
595 class_device_remove_file(class_dev, class_dev->devt_attr);
596 kfree(class_dev->devt_attr);
597 class_dev->devt_attr = NULL;
598 }
463 class_device_remove_attrs(class_dev); 599 class_device_remove_attrs(class_dev);
464 600
465 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); 601 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@@ -477,6 +613,32 @@ void class_device_unregister(struct class_device *class_dev)
477 class_device_put(class_dev); 613 class_device_put(class_dev);
478} 614}
479 615
616/**
617 * class_device_destroy - removes a class device that was created with class_device_create()
618 * @cls: the pointer to the struct class that this device was registered * with.
619 * @dev: the dev_t of the device that was previously registered.
620 *
621 * This call unregisters and cleans up a class device that was created with a
622 * call to class_device_create()
623 */
624void class_device_destroy(struct class *cls, dev_t devt)
625{
626 struct class_device *class_dev = NULL;
627 struct class_device *class_dev_tmp;
628
629 down(&cls->sem);
630 list_for_each_entry(class_dev_tmp, &cls->children, node) {
631 if (class_dev_tmp->devt == devt) {
632 class_dev = class_dev_tmp;
633 break;
634 }
635 }
636 up(&cls->sem);
637
638 if (class_dev)
639 class_device_unregister(class_dev);
640}
641
480int class_device_rename(struct class_device *class_dev, char *new_name) 642int class_device_rename(struct class_device *class_dev, char *new_name)
481{ 643{
482 int error = 0; 644 int error = 0;
@@ -576,6 +738,8 @@ EXPORT_SYMBOL_GPL(class_register);
576EXPORT_SYMBOL_GPL(class_unregister); 738EXPORT_SYMBOL_GPL(class_unregister);
577EXPORT_SYMBOL_GPL(class_get); 739EXPORT_SYMBOL_GPL(class_get);
578EXPORT_SYMBOL_GPL(class_put); 740EXPORT_SYMBOL_GPL(class_put);
741EXPORT_SYMBOL_GPL(class_create);
742EXPORT_SYMBOL_GPL(class_destroy);
579 743
580EXPORT_SYMBOL_GPL(class_device_register); 744EXPORT_SYMBOL_GPL(class_device_register);
581EXPORT_SYMBOL_GPL(class_device_unregister); 745EXPORT_SYMBOL_GPL(class_device_unregister);
@@ -584,6 +748,8 @@ EXPORT_SYMBOL_GPL(class_device_add);
584EXPORT_SYMBOL_GPL(class_device_del); 748EXPORT_SYMBOL_GPL(class_device_del);
585EXPORT_SYMBOL_GPL(class_device_get); 749EXPORT_SYMBOL_GPL(class_device_get);
586EXPORT_SYMBOL_GPL(class_device_put); 750EXPORT_SYMBOL_GPL(class_device_put);
751EXPORT_SYMBOL_GPL(class_device_create);
752EXPORT_SYMBOL_GPL(class_device_destroy);
587EXPORT_SYMBOL_GPL(class_device_create_file); 753EXPORT_SYMBOL_GPL(class_device_create_file);
588EXPORT_SYMBOL_GPL(class_device_remove_file); 754EXPORT_SYMBOL_GPL(class_device_remove_file);
589EXPORT_SYMBOL_GPL(class_device_create_bin_file); 755EXPORT_SYMBOL_GPL(class_device_create_bin_file);