aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-12-08 01:07:56 -0500
committerDmitry Torokhov <dtor@insightbb.com>2006-12-08 01:07:56 -0500
commitbef986502fa398b1785a3979b1aa17cd902d3527 (patch)
treeb59c1afe7b1dfcc001b86e54863f550d7ddc8c34 /drivers/base/core.c
parent4bdbd2807deeccc0793d57fb5120d7a53f2c0b3c (diff)
parentc99767974ebd2a719d849fdeaaa1674456f5283f (diff)
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/usb/input/hid.h
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c242
1 files changed, 222 insertions, 20 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 68ad11af22b4..67b79a7592a9 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -17,6 +17,7 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/kdev_t.h> 19#include <linux/kdev_t.h>
20#include <linux/notifier.h>
20 21
21#include <asm/semaphore.h> 22#include <asm/semaphore.h>
22 23
@@ -153,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
153 "MINOR=%u", MINOR(dev->devt)); 154 "MINOR=%u", MINOR(dev->devt));
154 } 155 }
155 156
157#ifdef CONFIG_SYSFS_DEPRECATED
156 /* add bus name (same as SUBSYSTEM, deprecated) */ 158 /* add bus name (same as SUBSYSTEM, deprecated) */
157 if (dev->bus) 159 if (dev->bus)
158 add_uevent_var(envp, num_envp, &i, 160 add_uevent_var(envp, num_envp, &i,
159 buffer, buffer_size, &length, 161 buffer, buffer_size, &length,
160 "PHYSDEVBUS=%s", dev->bus->name); 162 "PHYSDEVBUS=%s", dev->bus->name);
163#endif
161 164
162 /* add driver name (PHYSDEV* values are deprecated)*/ 165 /* add driver name (PHYSDEV* values are deprecated)*/
163 if (dev->driver) { 166 if (dev->driver) {
164 add_uevent_var(envp, num_envp, &i, 167 add_uevent_var(envp, num_envp, &i,
165 buffer, buffer_size, &length, 168 buffer, buffer_size, &length,
166 "DRIVER=%s", dev->driver->name); 169 "DRIVER=%s", dev->driver->name);
170#ifdef CONFIG_SYSFS_DEPRECATED
167 add_uevent_var(envp, num_envp, &i, 171 add_uevent_var(envp, num_envp, &i,
168 buffer, buffer_size, &length, 172 buffer, buffer_size, &length,
169 "PHYSDEVDRIVER=%s", dev->driver->name); 173 "PHYSDEVDRIVER=%s", dev->driver->name);
174#endif
170 } 175 }
171 176
172 /* terminate, set to next free slot, shrink available space */ 177 /* terminate, set to next free slot, shrink available space */
@@ -381,8 +386,55 @@ void device_initialize(struct device *dev)
381 INIT_LIST_HEAD(&dev->node); 386 INIT_LIST_HEAD(&dev->node);
382 init_MUTEX(&dev->sem); 387 init_MUTEX(&dev->sem);
383 device_init_wakeup(dev, 0); 388 device_init_wakeup(dev, 0);
389 set_dev_node(dev, -1);
384} 390}
385 391
392#ifdef CONFIG_SYSFS_DEPRECATED
393static int setup_parent(struct device *dev, struct device *parent)
394{
395 /* Set the parent to the class, not the parent device */
396 /* this keeps sysfs from having a symlink to make old udevs happy */
397 if (dev->class)
398 dev->kobj.parent = &dev->class->subsys.kset.kobj;
399 else if (parent)
400 dev->kobj.parent = &parent->kobj;
401
402 return 0;
403}
404#else
405static int virtual_device_parent(struct device *dev)
406{
407 if (!dev->class)
408 return -ENODEV;
409
410 if (!dev->class->virtual_dir) {
411 static struct kobject *virtual_dir = NULL;
412
413 if (!virtual_dir)
414 virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
415 dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
416 }
417
418 dev->kobj.parent = dev->class->virtual_dir;
419 return 0;
420}
421
422static int setup_parent(struct device *dev, struct device *parent)
423{
424 int error;
425
426 /* if this is a class device, and has no parent, create one */
427 if ((dev->class) && (parent == NULL)) {
428 error = virtual_device_parent(dev);
429 if (error)
430 return error;
431 } else if (parent)
432 dev->kobj.parent = &parent->kobj;
433
434 return 0;
435}
436#endif
437
386/** 438/**
387 * device_add - add device to device hierarchy. 439 * device_add - add device to device hierarchy.
388 * @dev: device. 440 * @dev: device.
@@ -405,29 +457,29 @@ int device_add(struct device *dev)
405 if (!dev || !strlen(dev->bus_id)) 457 if (!dev || !strlen(dev->bus_id))
406 goto Error; 458 goto Error;
407 459
408 /* if this is a class device, and has no parent, create one */ 460 pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
409 if ((dev->class) && (dev->parent == NULL)) {
410 error = virtual_device_parent(dev);
411 if (error)
412 goto Error;
413 }
414 461
415 parent = get_device(dev->parent); 462 parent = get_device(dev->parent);
416 463
417 pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); 464 error = setup_parent(dev, parent);
465 if (error)
466 goto Error;
418 467
419 /* first, register with generic layer. */ 468 /* first, register with generic layer. */
420 kobject_set_name(&dev->kobj, "%s", dev->bus_id); 469 kobject_set_name(&dev->kobj, "%s", dev->bus_id);
421 if (parent) 470 error = kobject_add(&dev->kobj);
422 dev->kobj.parent = &parent->kobj; 471 if (error)
423
424 if ((error = kobject_add(&dev->kobj)))
425 goto Error; 472 goto Error;
426 473
427 /* notify platform of device entry */ 474 /* notify platform of device entry */
428 if (platform_notify) 475 if (platform_notify)
429 platform_notify(dev); 476 platform_notify(dev);
430 477
478 /* notify clients of device entry (new way) */
479 if (dev->bus)
480 blocking_notifier_call_chain(&dev->bus->bus_notifier,
481 BUS_NOTIFY_ADD_DEVICE, dev);
482
431 dev->uevent_attr.attr.name = "uevent"; 483 dev->uevent_attr.attr.name = "uevent";
432 dev->uevent_attr.attr.mode = S_IWUSR; 484 dev->uevent_attr.attr.mode = S_IWUSR;
433 if (dev->driver) 485 if (dev->driver)
@@ -461,13 +513,18 @@ int device_add(struct device *dev)
461 if (dev->class) { 513 if (dev->class) {
462 sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, 514 sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
463 "subsystem"); 515 "subsystem");
464 sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, 516 /* If this is not a "fake" compatible device, then create the
465 dev->bus_id); 517 * symlink from the class to the device. */
518 if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
519 sysfs_create_link(&dev->class->subsys.kset.kobj,
520 &dev->kobj, dev->bus_id);
521#ifdef CONFIG_SYSFS_DEPRECATED
466 if (parent) { 522 if (parent) {
467 sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); 523 sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
468 class_name = make_class_name(dev->class->name, &dev->kobj); 524 class_name = make_class_name(dev->class->name, &dev->kobj);
469 sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); 525 sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
470 } 526 }
527#endif
471 } 528 }
472 529
473 if ((error = device_add_attrs(dev))) 530 if ((error = device_add_attrs(dev)))
@@ -504,6 +561,9 @@ int device_add(struct device *dev)
504 BusError: 561 BusError:
505 device_pm_remove(dev); 562 device_pm_remove(dev);
506 PMError: 563 PMError:
564 if (dev->bus)
565 blocking_notifier_call_chain(&dev->bus->bus_notifier,
566 BUS_NOTIFY_DEL_DEVICE, dev);
507 device_remove_groups(dev); 567 device_remove_groups(dev);
508 GroupError: 568 GroupError:
509 device_remove_attrs(dev); 569 device_remove_attrs(dev);
@@ -586,22 +646,31 @@ void put_device(struct device * dev)
586void device_del(struct device * dev) 646void device_del(struct device * dev)
587{ 647{
588 struct device * parent = dev->parent; 648 struct device * parent = dev->parent;
589 char *class_name = NULL;
590 struct class_interface *class_intf; 649 struct class_interface *class_intf;
591 650
592 if (parent) 651 if (parent)
593 klist_del(&dev->knode_parent); 652 klist_del(&dev->knode_parent);
594 if (dev->devt_attr) 653 if (dev->devt_attr) {
595 device_remove_file(dev, dev->devt_attr); 654 device_remove_file(dev, dev->devt_attr);
655 kfree(dev->devt_attr);
656 }
596 if (dev->class) { 657 if (dev->class) {
597 sysfs_remove_link(&dev->kobj, "subsystem"); 658 sysfs_remove_link(&dev->kobj, "subsystem");
598 sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); 659 /* If this is not a "fake" compatible device, remove the
599 class_name = make_class_name(dev->class->name, &dev->kobj); 660 * symlink from the class to the device. */
661 if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
662 sysfs_remove_link(&dev->class->subsys.kset.kobj,
663 dev->bus_id);
664#ifdef CONFIG_SYSFS_DEPRECATED
600 if (parent) { 665 if (parent) {
601 sysfs_remove_link(&dev->kobj, "device"); 666 char *class_name = make_class_name(dev->class->name,
667 &dev->kobj);
602 sysfs_remove_link(&dev->parent->kobj, class_name); 668 sysfs_remove_link(&dev->parent->kobj, class_name);
669 kfree(class_name);
670 sysfs_remove_link(&dev->kobj, "device");
603 } 671 }
604 kfree(class_name); 672#endif
673
605 down(&dev->class->sem); 674 down(&dev->class->sem);
606 /* notify any interfaces that the device is now gone */ 675 /* notify any interfaces that the device is now gone */
607 list_for_each_entry(class_intf, &dev->class->interfaces, node) 676 list_for_each_entry(class_intf, &dev->class->interfaces, node)
@@ -614,13 +683,16 @@ void device_del(struct device * dev)
614 device_remove_file(dev, &dev->uevent_attr); 683 device_remove_file(dev, &dev->uevent_attr);
615 device_remove_groups(dev); 684 device_remove_groups(dev);
616 device_remove_attrs(dev); 685 device_remove_attrs(dev);
686 bus_remove_device(dev);
617 687
618 /* Notify the platform of the removal, in case they 688 /* Notify the platform of the removal, in case they
619 * need to do anything... 689 * need to do anything...
620 */ 690 */
621 if (platform_notify_remove) 691 if (platform_notify_remove)
622 platform_notify_remove(dev); 692 platform_notify_remove(dev);
623 bus_remove_device(dev); 693 if (dev->bus)
694 blocking_notifier_call_chain(&dev->bus->bus_notifier,
695 BUS_NOTIFY_DEL_DEVICE, dev);
624 device_pm_remove(dev); 696 device_pm_remove(dev);
625 kobject_uevent(&dev->kobj, KOBJ_REMOVE); 697 kobject_uevent(&dev->kobj, KOBJ_REMOVE);
626 kobject_del(&dev->kobj); 698 kobject_del(&dev->kobj);
@@ -679,12 +751,45 @@ int device_for_each_child(struct device * parent, void * data,
679 return error; 751 return error;
680} 752}
681 753
754/**
755 * device_find_child - device iterator for locating a particular device.
756 * @parent: parent struct device
757 * @data: Data to pass to match function
758 * @match: Callback function to check device
759 *
760 * This is similar to the device_for_each_child() function above, but it
761 * returns a reference to a device that is 'found' for later use, as
762 * determined by the @match callback.
763 *
764 * The callback should return 0 if the device doesn't match and non-zero
765 * if it does. If the callback returns non-zero and a reference to the
766 * current device can be obtained, this function will return to the caller
767 * and not iterate over any more devices.
768 */
769struct device * device_find_child(struct device *parent, void *data,
770 int (*match)(struct device *, void *))
771{
772 struct klist_iter i;
773 struct device *child;
774
775 if (!parent)
776 return NULL;
777
778 klist_iter_init(&parent->klist_children, &i);
779 while ((child = next_device(&i)))
780 if (match(child, data) && get_device(child))
781 break;
782 klist_iter_exit(&i);
783 return child;
784}
785
682int __init devices_init(void) 786int __init devices_init(void)
683{ 787{
684 return subsystem_register(&devices_subsys); 788 return subsystem_register(&devices_subsys);
685} 789}
686 790
687EXPORT_SYMBOL_GPL(device_for_each_child); 791EXPORT_SYMBOL_GPL(device_for_each_child);
792EXPORT_SYMBOL_GPL(device_find_child);
688 793
689EXPORT_SYMBOL_GPL(device_initialize); 794EXPORT_SYMBOL_GPL(device_initialize);
690EXPORT_SYMBOL_GPL(device_add); 795EXPORT_SYMBOL_GPL(device_add);
@@ -807,8 +912,10 @@ int device_rename(struct device *dev, char *new_name)
807 912
808 pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name); 913 pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
809 914
915#ifdef CONFIG_SYSFS_DEPRECATED
810 if ((dev->class) && (dev->parent)) 916 if ((dev->class) && (dev->parent))
811 old_class_name = make_class_name(dev->class->name, &dev->kobj); 917 old_class_name = make_class_name(dev->class->name, &dev->kobj);
918#endif
812 919
813 if (dev->class) { 920 if (dev->class) {
814 old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); 921 old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
@@ -823,6 +930,7 @@ int device_rename(struct device *dev, char *new_name)
823 930
824 error = kobject_rename(&dev->kobj, new_name); 931 error = kobject_rename(&dev->kobj, new_name);
825 932
933#ifdef CONFIG_SYSFS_DEPRECATED
826 if (old_class_name) { 934 if (old_class_name) {
827 new_class_name = make_class_name(dev->class->name, &dev->kobj); 935 new_class_name = make_class_name(dev->class->name, &dev->kobj);
828 if (new_class_name) { 936 if (new_class_name) {
@@ -831,6 +939,8 @@ int device_rename(struct device *dev, char *new_name)
831 sysfs_remove_link(&dev->parent->kobj, old_class_name); 939 sysfs_remove_link(&dev->parent->kobj, old_class_name);
832 } 940 }
833 } 941 }
942#endif
943
834 if (dev->class) { 944 if (dev->class) {
835 sysfs_remove_link(&dev->class->subsys.kset.kobj, 945 sysfs_remove_link(&dev->class->subsys.kset.kobj,
836 old_symlink_name); 946 old_symlink_name);
@@ -846,3 +956,95 @@ int device_rename(struct device *dev, char *new_name)
846 956
847 return error; 957 return error;
848} 958}
959
960
961static int device_move_class_links(struct device *dev,
962 struct device *old_parent,
963 struct device *new_parent)
964{
965#ifdef CONFIG_SYSFS_DEPRECATED
966 int error;
967 char *class_name;
968
969 class_name = make_class_name(dev->class->name, &dev->kobj);
970 if (!class_name) {
971 error = PTR_ERR(class_name);
972 class_name = NULL;
973 goto out;
974 }
975 if (old_parent) {
976 sysfs_remove_link(&dev->kobj, "device");
977 sysfs_remove_link(&old_parent->kobj, class_name);
978 }
979 error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
980 if (error)
981 goto out;
982 error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
983 if (error)
984 sysfs_remove_link(&dev->kobj, "device");
985out:
986 kfree(class_name);
987 return error;
988#else
989 return 0;
990#endif
991}
992
993/**
994 * device_move - moves a device to a new parent
995 * @dev: the pointer to the struct device to be moved
996 * @new_parent: the new parent of the device
997 */
998int device_move(struct device *dev, struct device *new_parent)
999{
1000 int error;
1001 struct device *old_parent;
1002
1003 dev = get_device(dev);
1004 if (!dev)
1005 return -EINVAL;
1006
1007 if (!device_is_registered(dev)) {
1008 error = -EINVAL;
1009 goto out;
1010 }
1011 new_parent = get_device(new_parent);
1012 if (!new_parent) {
1013 error = -EINVAL;
1014 goto out;
1015 }
1016 pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
1017 new_parent->bus_id);
1018 error = kobject_move(&dev->kobj, &new_parent->kobj);
1019 if (error) {
1020 put_device(new_parent);
1021 goto out;
1022 }
1023 old_parent = dev->parent;
1024 dev->parent = new_parent;
1025 if (old_parent)
1026 klist_remove(&dev->knode_parent);
1027 klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
1028 if (!dev->class)
1029 goto out_put;
1030 error = device_move_class_links(dev, old_parent, new_parent);
1031 if (error) {
1032 /* We ignore errors on cleanup since we're hosed anyway... */
1033 device_move_class_links(dev, new_parent, old_parent);
1034 if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
1035 klist_remove(&dev->knode_parent);
1036 if (old_parent)
1037 klist_add_tail(&dev->knode_parent,
1038 &old_parent->klist_children);
1039 }
1040 put_device(new_parent);
1041 goto out;
1042 }
1043out_put:
1044 put_device(old_parent);
1045out:
1046 put_device(dev);
1047 return error;
1048}
1049
1050EXPORT_SYMBOL_GPL(device_move);