aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/base/class.c145
-rw-r--r--include/linux/device.h9
2 files changed, 143 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);
diff --git a/include/linux/device.h b/include/linux/device.h
index fa9e6ca08f5a..73250d01c01f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -143,6 +143,7 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
143 */ 143 */
144struct class { 144struct class {
145 const char * name; 145 const char * name;
146 struct module * owner;
146 147
147 struct subsystem subsys; 148 struct subsystem subsys;
148 struct list_head children; 149 struct list_head children;
@@ -185,6 +186,7 @@ struct class_device {
185 struct kobject kobj; 186 struct kobject kobj;
186 struct class * class; /* required */ 187 struct class * class; /* required */
187 dev_t devt; /* dev_t, creates the sysfs "dev" */ 188 dev_t devt; /* dev_t, creates the sysfs "dev" */
189 struct class_device_attribute *devt_attr;
188 struct device * dev; /* not necessary, but nice to have */ 190 struct device * dev; /* not necessary, but nice to have */
189 void * class_data; /* class-specific data */ 191 void * class_data; /* class-specific data */
190 192
@@ -245,6 +247,13 @@ struct class_interface {
245extern int class_interface_register(struct class_interface *); 247extern int class_interface_register(struct class_interface *);
246extern void class_interface_unregister(struct class_interface *); 248extern void class_interface_unregister(struct class_interface *);
247 249
250extern struct class *class_create(struct module *owner, char *name);
251extern void class_destroy(struct class *cls);
252extern struct class_device *class_device_create(struct class *cls, dev_t devt,
253 struct device *device, char *fmt, ...)
254 __attribute__((format(printf,4,5)));
255extern void class_device_destroy(struct class *cls, dev_t devt);
256
248/* interface for class simple stuff */ 257/* interface for class simple stuff */
249extern struct class_simple *class_simple_create(struct module *owner, char *name); 258extern struct class_simple *class_simple_create(struct module *owner, char *name);
250extern void class_simple_destroy(struct class_simple *cs); 259extern void class_simple_destroy(struct class_simple *cs);