diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index cf2a398aaaa1..d7fcf823a42a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -28,20 +28,6 @@ int (*platform_notify)(struct device * dev) = NULL; | |||
28 | int (*platform_notify_remove)(struct device * dev) = NULL; | 28 | int (*platform_notify_remove)(struct device * dev) = NULL; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Detect the LANANA-assigned LOCAL/EXPERIMENTAL majors | ||
32 | */ | ||
33 | bool is_lanana_major(unsigned int major) | ||
34 | { | ||
35 | if (major >= 60 && major <= 63) | ||
36 | return 1; | ||
37 | if (major >= 120 && major <= 127) | ||
38 | return 1; | ||
39 | if (major >= 240 && major <= 254) | ||
40 | return 1; | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * sysfs bindings for devices. | 31 | * sysfs bindings for devices. |
46 | */ | 32 | */ |
47 | 33 | ||
@@ -407,6 +393,35 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) | |||
407 | } | 393 | } |
408 | EXPORT_SYMBOL_GPL(device_remove_bin_file); | 394 | EXPORT_SYMBOL_GPL(device_remove_bin_file); |
409 | 395 | ||
396 | /** | ||
397 | * device_schedule_callback - helper to schedule a callback for a device | ||
398 | * @dev: device. | ||
399 | * @func: callback function to invoke later. | ||
400 | * | ||
401 | * Attribute methods must not unregister themselves or their parent device | ||
402 | * (which would amount to the same thing). Attempts to do so will deadlock, | ||
403 | * since unregistration is mutually exclusive with driver callbacks. | ||
404 | * | ||
405 | * Instead methods can call this routine, which will attempt to allocate | ||
406 | * and schedule a workqueue request to call back @func with @dev as its | ||
407 | * argument in the workqueue's process context. @dev will be pinned until | ||
408 | * @func returns. | ||
409 | * | ||
410 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | ||
411 | * be allocated. | ||
412 | * | ||
413 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an | ||
414 | * underlying sysfs routine (since it is intended for use by attribute | ||
415 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. | ||
416 | */ | ||
417 | int device_schedule_callback(struct device *dev, | ||
418 | void (*func)(struct device *)) | ||
419 | { | ||
420 | return sysfs_schedule_callback(&dev->kobj, | ||
421 | (void (*)(void *)) func, dev); | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(device_schedule_callback); | ||
424 | |||
410 | static void klist_children_get(struct klist_node *n) | 425 | static void klist_children_get(struct klist_node *n) |
411 | { | 426 | { |
412 | struct device *dev = container_of(n, struct device, knode_parent); | 427 | struct device *dev = container_of(n, struct device, knode_parent); |
@@ -584,17 +599,17 @@ int device_add(struct device *dev) | |||
584 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | 599 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) |
585 | sysfs_create_link(&dev->class->subsys.kset.kobj, | 600 | sysfs_create_link(&dev->class->subsys.kset.kobj, |
586 | &dev->kobj, dev->bus_id); | 601 | &dev->kobj, dev->bus_id); |
587 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
588 | if (parent) { | 602 | if (parent) { |
589 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, | 603 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, |
590 | "device"); | 604 | "device"); |
605 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
591 | class_name = make_class_name(dev->class->name, | 606 | class_name = make_class_name(dev->class->name, |
592 | &dev->kobj); | 607 | &dev->kobj); |
593 | if (class_name) | 608 | if (class_name) |
594 | sysfs_create_link(&dev->parent->kobj, | 609 | sysfs_create_link(&dev->parent->kobj, |
595 | &dev->kobj, class_name); | 610 | &dev->kobj, class_name); |
596 | } | ||
597 | #endif | 611 | #endif |
612 | } | ||
598 | } | 613 | } |
599 | 614 | ||
600 | if ((error = device_add_attrs(dev))) | 615 | if ((error = device_add_attrs(dev))) |
@@ -651,17 +666,17 @@ int device_add(struct device *dev) | |||
651 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | 666 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) |
652 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | 667 | sysfs_remove_link(&dev->class->subsys.kset.kobj, |
653 | dev->bus_id); | 668 | dev->bus_id); |
654 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
655 | if (parent) { | 669 | if (parent) { |
670 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
656 | char *class_name = make_class_name(dev->class->name, | 671 | char *class_name = make_class_name(dev->class->name, |
657 | &dev->kobj); | 672 | &dev->kobj); |
658 | if (class_name) | 673 | if (class_name) |
659 | sysfs_remove_link(&dev->parent->kobj, | 674 | sysfs_remove_link(&dev->parent->kobj, |
660 | class_name); | 675 | class_name); |
661 | kfree(class_name); | 676 | kfree(class_name); |
677 | #endif | ||
662 | sysfs_remove_link(&dev->kobj, "device"); | 678 | sysfs_remove_link(&dev->kobj, "device"); |
663 | } | 679 | } |
664 | #endif | ||
665 | 680 | ||
666 | down(&dev->class->sem); | 681 | down(&dev->class->sem); |
667 | /* notify any interfaces that the device is now gone */ | 682 | /* notify any interfaces that the device is now gone */ |
@@ -761,17 +776,17 @@ void device_del(struct device * dev) | |||
761 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | 776 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) |
762 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | 777 | sysfs_remove_link(&dev->class->subsys.kset.kobj, |
763 | dev->bus_id); | 778 | dev->bus_id); |
764 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
765 | if (parent) { | 779 | if (parent) { |
780 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
766 | char *class_name = make_class_name(dev->class->name, | 781 | char *class_name = make_class_name(dev->class->name, |
767 | &dev->kobj); | 782 | &dev->kobj); |
768 | if (class_name) | 783 | if (class_name) |
769 | sysfs_remove_link(&dev->parent->kobj, | 784 | sysfs_remove_link(&dev->parent->kobj, |
770 | class_name); | 785 | class_name); |
771 | kfree(class_name); | 786 | kfree(class_name); |
787 | #endif | ||
772 | sysfs_remove_link(&dev->kobj, "device"); | 788 | sysfs_remove_link(&dev->kobj, "device"); |
773 | } | 789 | } |
774 | #endif | ||
775 | 790 | ||
776 | down(&dev->class->sem); | 791 | down(&dev->class->sem); |
777 | /* notify any interfaces that the device is now gone */ | 792 | /* notify any interfaces that the device is now gone */ |
@@ -787,6 +802,13 @@ void device_del(struct device * dev) | |||
787 | device_remove_attrs(dev); | 802 | device_remove_attrs(dev); |
788 | bus_remove_device(dev); | 803 | bus_remove_device(dev); |
789 | 804 | ||
805 | /* | ||
806 | * Some platform devices are driven without driver attached | ||
807 | * and managed resources may have been acquired. Make sure | ||
808 | * all resources are released. | ||
809 | */ | ||
810 | devres_release_all(dev); | ||
811 | |||
790 | /* Notify the platform of the removal, in case they | 812 | /* Notify the platform of the removal, in case they |
791 | * need to do anything... | 813 | * need to do anything... |
792 | */ | 814 | */ |
@@ -1058,14 +1080,14 @@ int device_rename(struct device *dev, char *new_name) | |||
1058 | 1080 | ||
1059 | return error; | 1081 | return error; |
1060 | } | 1082 | } |
1061 | 1083 | EXPORT_SYMBOL_GPL(device_rename); | |
1062 | 1084 | ||
1063 | static int device_move_class_links(struct device *dev, | 1085 | static int device_move_class_links(struct device *dev, |
1064 | struct device *old_parent, | 1086 | struct device *old_parent, |
1065 | struct device *new_parent) | 1087 | struct device *new_parent) |
1066 | { | 1088 | { |
1089 | int error = 0; | ||
1067 | #ifdef CONFIG_SYSFS_DEPRECATED | 1090 | #ifdef CONFIG_SYSFS_DEPRECATED |
1068 | int error; | ||
1069 | char *class_name; | 1091 | char *class_name; |
1070 | 1092 | ||
1071 | class_name = make_class_name(dev->class->name, &dev->kobj); | 1093 | class_name = make_class_name(dev->class->name, &dev->kobj); |
@@ -1093,7 +1115,12 @@ out: | |||
1093 | kfree(class_name); | 1115 | kfree(class_name); |
1094 | return error; | 1116 | return error; |
1095 | #else | 1117 | #else |
1096 | return 0; | 1118 | if (old_parent) |
1119 | sysfs_remove_link(&dev->kobj, "device"); | ||
1120 | if (new_parent) | ||
1121 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, | ||
1122 | "device"); | ||
1123 | return error; | ||
1097 | #endif | 1124 | #endif |
1098 | } | 1125 | } |
1099 | 1126 | ||