aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 01:25:43 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 12:52:51 -0400
commit51d172d5f3a193e4b8f76179b2e55d7a36b94117 (patch)
tree4bb508d85d9de2588235caddf197da57a47b5d6e
parenta7fd67062efc5b0fc9a61368c607fa92d1d57f9e (diff)
[PATCH] Driver Core: add the ability for class_device structures to be nested
This patch allows struct class_device to be nested, so that another struct class_device can be the parent of a new one, instead of only having the struct class be the parent. This will allow us to (hopefully) fix up the input and video class subsystem mess. But please people, don't go crazy and start making huge trees of class devices, you should only need 2 levels deep to get everything to work (remember to use a class_interface to get notification of a new class device being added to the system.) Oh, this also allows us to have the possibility of potentially, someday, moving /sys/block into /sys/class. The main hindrance is that pesky /dev numberspace issue... Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/base/class.c125
-rw-r--r--include/linux/device.h13
2 files changed, 91 insertions, 47 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 3cf6eb36f3d8..c3e569730afe 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -99,7 +99,8 @@ struct class * class_get(struct class * cls)
99 99
100void class_put(struct class * cls) 100void class_put(struct class * cls)
101{ 101{
102 subsys_put(&cls->subsys); 102 if (cls)
103 subsys_put(&cls->subsys);
103} 104}
104 105
105 106
@@ -165,14 +166,25 @@ void class_unregister(struct class * cls)
165 166
166static void class_create_release(struct class *cls) 167static void class_create_release(struct class *cls)
167{ 168{
169 pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
168 kfree(cls); 170 kfree(cls);
169} 171}
170 172
171static void class_device_create_release(struct class_device *class_dev) 173static void class_device_create_release(struct class_device *class_dev)
172{ 174{
175 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
173 kfree(class_dev); 176 kfree(class_dev);
174} 177}
175 178
179/* needed to allow these devices to have parent class devices */
180static int class_device_create_hotplug(struct class_device *class_dev,
181 char **envp, int num_envp,
182 char *buffer, int buffer_size)
183{
184 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
185 return 0;
186}
187
176/** 188/**
177 * class_create - create a struct class structure 189 * class_create - create a struct class structure
178 * @owner: pointer to the module that is to "own" this struct class 190 * @owner: pointer to the module that is to "own" this struct class
@@ -301,10 +313,12 @@ static void class_dev_release(struct kobject * kobj)
301 kfree(cd->devt_attr); 313 kfree(cd->devt_attr);
302 cd->devt_attr = NULL; 314 cd->devt_attr = NULL;
303 315
304 if (cls->release) 316 if (cd->release)
317 cd->release(cd);
318 else if (cls->release)
305 cls->release(cd); 319 cls->release(cd);
306 else { 320 else {
307 printk(KERN_ERR "Device class '%s' does not have a release() function, " 321 printk(KERN_ERR "Class Device '%s' does not have a release() function, "
308 "it is broken and must be fixed.\n", 322 "it is broken and must be fixed.\n",
309 cd->class_id); 323 cd->class_id);
310 WARN_ON(1); 324 WARN_ON(1);
@@ -382,14 +396,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
382 buffer = &buffer[length]; 396 buffer = &buffer[length];
383 buffer_size -= length; 397 buffer_size -= length;
384 398
385 if (class_dev->class->hotplug) { 399 if (class_dev->hotplug) {
386 /* have the bus specific function add its stuff */ 400 /* have the class device specific function add its stuff */
387 retval = class_dev->class->hotplug (class_dev, envp, num_envp, 401 retval = class_dev->hotplug(class_dev, envp, num_envp,
388 buffer, buffer_size); 402 buffer, buffer_size);
389 if (retval) { 403 if (retval)
390 pr_debug ("%s - hotplug() returned %d\n", 404 pr_debug("class_dev->hotplug() returned %d\n", retval);
391 __FUNCTION__, retval); 405 } else if (class_dev->class->hotplug) {
392 } 406 /* have the class specific function add its stuff */
407 retval = class_dev->class->hotplug(class_dev, envp, num_envp,
408 buffer, buffer_size);
409 if (retval)
410 pr_debug("class->hotplug() returned %d\n", retval);
393 } 411 }
394 412
395 return retval; 413 return retval;
@@ -476,37 +494,42 @@ static char *make_class_name(struct class_device *class_dev)
476 494
477int class_device_add(struct class_device *class_dev) 495int class_device_add(struct class_device *class_dev)
478{ 496{
479 struct class * parent = NULL; 497 struct class *parent_class = NULL;
480 struct class_interface * class_intf; 498 struct class_device *parent_class_dev = NULL;
499 struct class_interface *class_intf;
481 char *class_name = NULL; 500 char *class_name = NULL;
482 int error; 501 int error = -EINVAL;
483 502
484 class_dev = class_device_get(class_dev); 503 class_dev = class_device_get(class_dev);
485 if (!class_dev) 504 if (!class_dev)
486 return -EINVAL; 505 return -EINVAL;
487 506
488 if (!strlen(class_dev->class_id)) { 507 if (!strlen(class_dev->class_id))
489 error = -EINVAL;
490 goto register_done; 508 goto register_done;
491 }
492 509
493 parent = class_get(class_dev->class); 510 parent_class = class_get(class_dev->class);
511 if (!parent_class)
512 goto register_done;
513 parent_class_dev = class_device_get(class_dev->parent);
494 514
495 pr_debug("CLASS: registering class device: ID = '%s'\n", 515 pr_debug("CLASS: registering class device: ID = '%s'\n",
496 class_dev->class_id); 516 class_dev->class_id);
497 517
498 /* first, register with generic layer. */ 518 /* first, register with generic layer. */
499 kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); 519 kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
500 if (parent) 520 if (parent_class_dev)
501 class_dev->kobj.parent = &parent->subsys.kset.kobj; 521 class_dev->kobj.parent = &parent_class_dev->kobj;
522 else
523 class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
502 524
503 if ((error = kobject_add(&class_dev->kobj))) 525 error = kobject_add(&class_dev->kobj);
526 if (error)
504 goto register_done; 527 goto register_done;
505 528
506 /* add the needed attributes to this device */ 529 /* add the needed attributes to this device */
507 class_dev->uevent_attr.attr.name = "uevent"; 530 class_dev->uevent_attr.attr.name = "uevent";
508 class_dev->uevent_attr.attr.mode = S_IWUSR; 531 class_dev->uevent_attr.attr.mode = S_IWUSR;
509 class_dev->uevent_attr.attr.owner = parent->owner; 532 class_dev->uevent_attr.attr.owner = parent_class->owner;
510 class_dev->uevent_attr.store = store_uevent; 533 class_dev->uevent_attr.store = store_uevent;
511 class_device_create_file(class_dev, &class_dev->uevent_attr); 534 class_device_create_file(class_dev, &class_dev->uevent_attr);
512 535
@@ -520,7 +543,7 @@ int class_device_add(struct class_device *class_dev)
520 } 543 }
521 attr->attr.name = "dev"; 544 attr->attr.name = "dev";
522 attr->attr.mode = S_IRUGO; 545 attr->attr.mode = S_IRUGO;
523 attr->attr.owner = parent->owner; 546 attr->attr.owner = parent_class->owner;
524 attr->show = show_dev; 547 attr->show = show_dev;
525 class_device_create_file(class_dev, attr); 548 class_device_create_file(class_dev, attr);
526 class_dev->devt_attr = attr; 549 class_dev->devt_attr = attr;
@@ -538,18 +561,20 @@ int class_device_add(struct class_device *class_dev)
538 kobject_hotplug(&class_dev->kobj, KOBJ_ADD); 561 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
539 562
540 /* notify any interfaces this device is now here */ 563 /* notify any interfaces this device is now here */
541 if (parent) { 564 if (parent_class) {
542 down(&parent->sem); 565 down(&parent_class->sem);
543 list_add_tail(&class_dev->node, &parent->children); 566 list_add_tail(&class_dev->node, &parent_class->children);
544 list_for_each_entry(class_intf, &parent->interfaces, node) 567 list_for_each_entry(class_intf, &parent_class->interfaces, node)
545 if (class_intf->add) 568 if (class_intf->add)
546 class_intf->add(class_dev, class_intf); 569 class_intf->add(class_dev, class_intf);
547 up(&parent->sem); 570 up(&parent_class->sem);
548 } 571 }
549 572
550 register_done: 573 register_done:
551 if (error && parent) 574 if (error) {
552 class_put(parent); 575 class_put(parent_class);
576 class_device_put(parent_class_dev);
577 }
553 class_device_put(class_dev); 578 class_device_put(class_dev);
554 kfree(class_name); 579 kfree(class_name);
555 return error; 580 return error;
@@ -564,21 +589,28 @@ int class_device_register(struct class_device *class_dev)
564/** 589/**
565 * class_device_create - creates a class device and registers it with sysfs 590 * class_device_create - creates a class device and registers it with sysfs
566 * @cs: pointer to the struct class that this device should be registered to. 591 * @cs: pointer to the struct class that this device should be registered to.
592 * @parent: pointer to the parent struct class_device of this new device, if any.
567 * @dev: the dev_t for the char device to be added. 593 * @dev: the dev_t for the char device to be added.
568 * @device: a pointer to a struct device that is assiociated with this class device. 594 * @device: a pointer to a struct device that is assiociated with this class device.
569 * @fmt: string for the class device's name 595 * @fmt: string for the class device's name
570 * 596 *
571 * This function can be used by char device classes. A struct 597 * This function can be used by char device classes. A struct
572 * class_device will be created in sysfs, registered to the specified 598 * class_device will be created in sysfs, registered to the specified
573 * class. A "dev" file will be created, showing the dev_t for the 599 * class.
574 * device. The pointer to the struct class_device will be returned from 600 * A "dev" file will be created, showing the dev_t for the device, if
575 * the call. Any further sysfs files that might be required can be 601 * the dev_t is not 0,0.
576 * created using this pointer. 602 * If a pointer to a parent struct class_device is passed in, the newly
603 * created struct class_device will be a child of that device in sysfs.
604 * The pointer to the struct class_device will be returned from the
605 * call. Any further sysfs files that might be required can be created
606 * using this pointer.
577 * 607 *
578 * Note: the struct class passed to this function must have previously 608 * Note: the struct class passed to this function must have previously
579 * been created with a call to class_create(). 609 * been created with a call to class_create().
580 */ 610 */
581struct class_device *class_device_create(struct class *cls, dev_t devt, 611struct class_device *class_device_create(struct class *cls,
612 struct class_device *parent,
613 dev_t devt,
582 struct device *device, char *fmt, ...) 614 struct device *device, char *fmt, ...)
583{ 615{
584 va_list args; 616 va_list args;
@@ -597,6 +629,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
597 class_dev->devt = devt; 629 class_dev->devt = devt;
598 class_dev->dev = device; 630 class_dev->dev = device;
599 class_dev->class = cls; 631 class_dev->class = cls;
632 class_dev->parent = parent;
633 class_dev->release = class_device_create_release;
634 class_dev->hotplug = class_device_create_hotplug;
600 635
601 va_start(args, fmt); 636 va_start(args, fmt);
602 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args); 637 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -614,17 +649,18 @@ error:
614 649
615void class_device_del(struct class_device *class_dev) 650void class_device_del(struct class_device *class_dev)
616{ 651{
617 struct class * parent = class_dev->class; 652 struct class *parent_class = class_dev->class;
618 struct class_interface * class_intf; 653 struct class_device *parent_device = class_dev->parent;
654 struct class_interface *class_intf;
619 char *class_name = NULL; 655 char *class_name = NULL;
620 656
621 if (parent) { 657 if (parent_class) {
622 down(&parent->sem); 658 down(&parent_class->sem);
623 list_del_init(&class_dev->node); 659 list_del_init(&class_dev->node);
624 list_for_each_entry(class_intf, &parent->interfaces, node) 660 list_for_each_entry(class_intf, &parent_class->interfaces, node)
625 if (class_intf->remove) 661 if (class_intf->remove)
626 class_intf->remove(class_dev, class_intf); 662 class_intf->remove(class_dev, class_intf);
627 up(&parent->sem); 663 up(&parent_class->sem);
628 } 664 }
629 665
630 if (class_dev->dev) { 666 if (class_dev->dev) {
@@ -640,8 +676,8 @@ void class_device_del(struct class_device *class_dev)
640 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); 676 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
641 kobject_del(&class_dev->kobj); 677 kobject_del(&class_dev->kobj);
642 678
643 if (parent) 679 class_device_put(parent_device);
644 class_put(parent); 680 class_put(parent_class);
645 kfree(class_name); 681 kfree(class_name);
646} 682}
647 683
@@ -721,7 +757,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
721 757
722void class_device_put(struct class_device *class_dev) 758void class_device_put(struct class_device *class_dev)
723{ 759{
724 kobject_put(&class_dev->kobj); 760 if (class_dev)
761 kobject_put(&class_dev->kobj);
725} 762}
726 763
727 764
diff --git a/include/linux/device.h b/include/linux/device.h
index e86a580b72e1..226e550ae2ea 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -213,7 +213,11 @@ struct class_device {
213 struct class_device_attribute uevent_attr; 213 struct class_device_attribute uevent_attr;
214 struct device * dev; /* not necessary, but nice to have */ 214 struct device * dev; /* not necessary, but nice to have */
215 void * class_data; /* class-specific data */ 215 void * class_data; /* class-specific data */
216 struct class_device *parent; /* parent of this child device, if there is one */
216 217
218 void (*release)(struct class_device *dev);
219 int (*hotplug)(struct class_device *dev, char **envp,
220 int num_envp, char *buffer, int buffer_size);
217 char class_id[BUS_ID_SIZE]; /* unique to this class */ 221 char class_id[BUS_ID_SIZE]; /* unique to this class */
218}; 222};
219 223
@@ -261,9 +265,12 @@ extern void class_interface_unregister(struct class_interface *);
261 265
262extern struct class *class_create(struct module *owner, char *name); 266extern struct class *class_create(struct module *owner, char *name);
263extern void class_destroy(struct class *cls); 267extern void class_destroy(struct class *cls);
264extern struct class_device *class_device_create(struct class *cls, dev_t devt, 268extern struct class_device *class_device_create(struct class *cls,
265 struct device *device, char *fmt, ...) 269 struct class_device *parent,
266 __attribute__((format(printf,4,5))); 270 dev_t devt,
271 struct device *device,
272 char *fmt, ...)
273 __attribute__((format(printf,5,6)));
267extern void class_device_destroy(struct class *cls, dev_t devt); 274extern void class_device_destroy(struct class *cls, dev_t devt);
268 275
269 276