aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/class.c
diff options
context:
space:
mode:
authorgregkh@suse.de <gregkh@suse.de>2005-03-15 14:54:21 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-20 18:15:04 -0400
commite9ba6365fd4f0d9e7d022c883bd044fbaa48257f (patch)
tree062476167b5c9cd5ed08a01f223e71c2ece795ee /drivers/base/class.c
parent70f2817a43c89b784dc2ec3d06ba5bf3064f8235 (diff)
[PATCH] CLASS: move a "simple" class logic into the class core.
One step on improving the class api so that it can not be used incorrectly. This also fixes the module owner issue with the dev files that happened when the devt logic moved to the class core. Based on a patch originally written by Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r--drivers/base/class.c145
1 files changed, 134 insertions, 11 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 344b8cd73901..a3b006b6f2ba 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)
@@ -162,6 +163,51 @@ 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
176struct class *class_create(struct module *owner, char *name)
177{
178 struct class *cls;
179 int retval;
180
181 cls = kmalloc(sizeof(struct class), GFP_KERNEL);
182 if (!cls) {
183 retval = -ENOMEM;
184 goto error;
185 }
186 memset(cls, 0x00, sizeof(struct class));
187
188 cls->name = name;
189 cls->owner = owner;
190 cls->class_release = class_create_release;
191 cls->release = class_device_create_release;
192
193 retval = class_register(cls);
194 if (retval)
195 goto error;
196
197 return cls;
198
199error:
200 kfree(cls);
201 return ERR_PTR(retval);
202}
203
204void class_destroy(struct class *cls)
205{
206 if ((cls == NULL) || (IS_ERR(cls)))
207 return;
208
209 class_unregister(cls);
210}
165 211
166/* Class Device Stuff */ 212/* Class Device Stuff */
167 213
@@ -375,7 +421,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
375{ 421{
376 return print_dev_t(buf, class_dev->devt); 422 return print_dev_t(buf, class_dev->devt);
377} 423}
378static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
379 424
380void class_device_initialize(struct class_device *class_dev) 425void class_device_initialize(struct class_device *class_dev)
381{ 426{
@@ -412,7 +457,31 @@ int class_device_add(struct class_device *class_dev)
412 if ((error = kobject_add(&class_dev->kobj))) 457 if ((error = kobject_add(&class_dev->kobj)))
413 goto register_done; 458 goto register_done;
414 459
415 /* now take care of our own registration */ 460 /* add the needed attributes to this device */
461 if (MAJOR(class_dev->devt)) {
462 struct class_device_attribute *attr;
463 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
464 if (!attr) {
465 error = -ENOMEM;
466 kobject_del(&class_dev->kobj);
467 goto register_done;
468 }
469 memset(attr, sizeof(*attr), 0x00);
470 attr->attr.name = "dev";
471 attr->attr.mode = S_IRUGO;
472 attr->attr.owner = parent->owner;
473 attr->show = show_dev;
474 attr->store = NULL;
475 class_device_create_file(class_dev, attr);
476 class_dev->devt_attr = attr;
477 }
478
479 class_device_add_attrs(class_dev);
480 if (class_dev->dev)
481 sysfs_create_link(&class_dev->kobj,
482 &class_dev->dev->kobj, "device");
483
484 /* notify any interfaces this device is now here */
416 if (parent) { 485 if (parent) {
417 down(&parent->sem); 486 down(&parent->sem);
418 list_add_tail(&class_dev->node, &parent->children); 487 list_add_tail(&class_dev->node, &parent->children);
@@ -421,16 +490,8 @@ int class_device_add(struct class_device *class_dev)
421 class_intf->add(class_dev); 490 class_intf->add(class_dev);
422 up(&parent->sem); 491 up(&parent->sem);
423 } 492 }
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); 493 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
494
434 register_done: 495 register_done:
435 if (error && parent) 496 if (error && parent)
436 class_put(parent); 497 class_put(parent);
@@ -444,6 +505,41 @@ int class_device_register(struct class_device *class_dev)
444 return class_device_add(class_dev); 505 return class_device_add(class_dev);
445} 506}
446 507
508struct class_device *class_device_create(struct class *cls, dev_t devt,
509 struct device *device, char *fmt, ...)
510{
511 va_list args;
512 struct class_device *class_dev = NULL;
513 int retval = -ENODEV;
514
515 if (cls == NULL || IS_ERR(cls))
516 goto error;
517
518 class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
519 if (!class_dev) {
520 retval = -ENOMEM;
521 goto error;
522 }
523 memset(class_dev, 0x00, sizeof(struct class_device));
524
525 class_dev->devt = devt;
526 class_dev->dev = device;
527 class_dev->class = cls;
528
529 va_start(args, fmt);
530 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
531 va_end(args);
532 retval = class_device_register(class_dev);
533 if (retval)
534 goto error;
535
536 return class_dev;
537
538error:
539 kfree(class_dev);
540 return ERR_PTR(retval);
541}
542
447void class_device_del(struct class_device *class_dev) 543void class_device_del(struct class_device *class_dev)
448{ 544{
449 struct class * parent = class_dev->class; 545 struct class * parent = class_dev->class;
@@ -460,6 +556,11 @@ void class_device_del(struct class_device *class_dev)
460 556
461 if (class_dev->dev) 557 if (class_dev->dev)
462 sysfs_remove_link(&class_dev->kobj, "device"); 558 sysfs_remove_link(&class_dev->kobj, "device");
559 if (class_dev->devt_attr) {
560 class_device_remove_file(class_dev, class_dev->devt_attr);
561 kfree(class_dev->devt_attr);
562 class_dev->devt_attr = NULL;
563 }
463 class_device_remove_attrs(class_dev); 564 class_device_remove_attrs(class_dev);
464 565
465 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); 566 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@@ -477,6 +578,24 @@ void class_device_unregister(struct class_device *class_dev)
477 class_device_put(class_dev); 578 class_device_put(class_dev);
478} 579}
479 580
581void class_device_destroy(struct class *cls, dev_t devt)
582{
583 struct class_device *class_dev = NULL;
584 struct class_device *class_dev_tmp;
585
586 down(&cls->sem);
587 list_for_each_entry(class_dev_tmp, &cls->children, node) {
588 if (class_dev_tmp->devt == devt) {
589 class_dev = class_dev_tmp;
590 break;
591 }
592 }
593 up(&cls->sem);
594
595 if (class_dev)
596 class_device_unregister(class_dev);
597}
598
480int class_device_rename(struct class_device *class_dev, char *new_name) 599int class_device_rename(struct class_device *class_dev, char *new_name)
481{ 600{
482 int error = 0; 601 int error = 0;
@@ -576,6 +695,8 @@ EXPORT_SYMBOL_GPL(class_register);
576EXPORT_SYMBOL_GPL(class_unregister); 695EXPORT_SYMBOL_GPL(class_unregister);
577EXPORT_SYMBOL_GPL(class_get); 696EXPORT_SYMBOL_GPL(class_get);
578EXPORT_SYMBOL_GPL(class_put); 697EXPORT_SYMBOL_GPL(class_put);
698EXPORT_SYMBOL_GPL(class_create);
699EXPORT_SYMBOL_GPL(class_destroy);
579 700
580EXPORT_SYMBOL_GPL(class_device_register); 701EXPORT_SYMBOL_GPL(class_device_register);
581EXPORT_SYMBOL_GPL(class_device_unregister); 702EXPORT_SYMBOL_GPL(class_device_unregister);
@@ -584,6 +705,8 @@ EXPORT_SYMBOL_GPL(class_device_add);
584EXPORT_SYMBOL_GPL(class_device_del); 705EXPORT_SYMBOL_GPL(class_device_del);
585EXPORT_SYMBOL_GPL(class_device_get); 706EXPORT_SYMBOL_GPL(class_device_get);
586EXPORT_SYMBOL_GPL(class_device_put); 707EXPORT_SYMBOL_GPL(class_device_put);
708EXPORT_SYMBOL_GPL(class_device_create);
709EXPORT_SYMBOL_GPL(class_device_destroy);
587EXPORT_SYMBOL_GPL(class_device_create_file); 710EXPORT_SYMBOL_GPL(class_device_create_file);
588EXPORT_SYMBOL_GPL(class_device_remove_file); 711EXPORT_SYMBOL_GPL(class_device_remove_file);
589EXPORT_SYMBOL_GPL(class_device_create_bin_file); 712EXPORT_SYMBOL_GPL(class_device_create_bin_file);