diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 2683eac30c68..ce6b64c489ad 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -726,11 +726,20 @@ int device_add(struct device *dev) | |||
726 | { | 726 | { |
727 | struct device *parent = NULL; | 727 | struct device *parent = NULL; |
728 | struct class_interface *class_intf; | 728 | struct class_interface *class_intf; |
729 | int error = -EINVAL; | 729 | int error; |
730 | |||
731 | error = pm_sleep_lock(); | ||
732 | if (error) { | ||
733 | dev_warn(dev, "Suspicious %s during suspend\n", __FUNCTION__); | ||
734 | dump_stack(); | ||
735 | return error; | ||
736 | } | ||
730 | 737 | ||
731 | dev = get_device(dev); | 738 | dev = get_device(dev); |
732 | if (!dev || !strlen(dev->bus_id)) | 739 | if (!dev || !strlen(dev->bus_id)) { |
740 | error = -EINVAL; | ||
733 | goto Error; | 741 | goto Error; |
742 | } | ||
734 | 743 | ||
735 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); | 744 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); |
736 | 745 | ||
@@ -795,6 +804,7 @@ int device_add(struct device *dev) | |||
795 | } | 804 | } |
796 | Done: | 805 | Done: |
797 | put_device(dev); | 806 | put_device(dev); |
807 | pm_sleep_unlock(); | ||
798 | return error; | 808 | return error; |
799 | BusError: | 809 | BusError: |
800 | device_pm_remove(dev); | 810 | device_pm_remove(dev); |
@@ -905,6 +915,7 @@ void device_del(struct device * dev) | |||
905 | struct device * parent = dev->parent; | 915 | struct device * parent = dev->parent; |
906 | struct class_interface *class_intf; | 916 | struct class_interface *class_intf; |
907 | 917 | ||
918 | device_pm_remove(dev); | ||
908 | if (parent) | 919 | if (parent) |
909 | klist_del(&dev->knode_parent); | 920 | klist_del(&dev->knode_parent); |
910 | if (MAJOR(dev->devt)) | 921 | if (MAJOR(dev->devt)) |
@@ -981,7 +992,6 @@ void device_del(struct device * dev) | |||
981 | if (dev->bus) | 992 | if (dev->bus) |
982 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | 993 | blocking_notifier_call_chain(&dev->bus->bus_notifier, |
983 | BUS_NOTIFY_DEL_DEVICE, dev); | 994 | BUS_NOTIFY_DEL_DEVICE, dev); |
984 | device_pm_remove(dev); | ||
985 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 995 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
986 | kobject_del(&dev->kobj); | 996 | kobject_del(&dev->kobj); |
987 | if (parent) | 997 | if (parent) |
@@ -1156,14 +1166,11 @@ error: | |||
1156 | EXPORT_SYMBOL_GPL(device_create); | 1166 | EXPORT_SYMBOL_GPL(device_create); |
1157 | 1167 | ||
1158 | /** | 1168 | /** |
1159 | * device_destroy - removes a device that was created with device_create() | 1169 | * find_device - finds a device that was created with device_create() |
1160 | * @class: pointer to the struct class that this device was registered with | 1170 | * @class: pointer to the struct class that this device was registered with |
1161 | * @devt: the dev_t of the device that was previously registered | 1171 | * @devt: the dev_t of the device that was previously registered |
1162 | * | ||
1163 | * This call unregisters and cleans up a device that was created with a | ||
1164 | * call to device_create(). | ||
1165 | */ | 1172 | */ |
1166 | void device_destroy(struct class *class, dev_t devt) | 1173 | static struct device *find_device(struct class *class, dev_t devt) |
1167 | { | 1174 | { |
1168 | struct device *dev = NULL; | 1175 | struct device *dev = NULL; |
1169 | struct device *dev_tmp; | 1176 | struct device *dev_tmp; |
@@ -1176,12 +1183,54 @@ void device_destroy(struct class *class, dev_t devt) | |||
1176 | } | 1183 | } |
1177 | } | 1184 | } |
1178 | up(&class->sem); | 1185 | up(&class->sem); |
1186 | return dev; | ||
1187 | } | ||
1179 | 1188 | ||
1189 | /** | ||
1190 | * device_destroy - removes a device that was created with device_create() | ||
1191 | * @class: pointer to the struct class that this device was registered with | ||
1192 | * @devt: the dev_t of the device that was previously registered | ||
1193 | * | ||
1194 | * This call unregisters and cleans up a device that was created with a | ||
1195 | * call to device_create(). | ||
1196 | */ | ||
1197 | void device_destroy(struct class *class, dev_t devt) | ||
1198 | { | ||
1199 | struct device *dev; | ||
1200 | |||
1201 | dev = find_device(class, devt); | ||
1180 | if (dev) | 1202 | if (dev) |
1181 | device_unregister(dev); | 1203 | device_unregister(dev); |
1182 | } | 1204 | } |
1183 | EXPORT_SYMBOL_GPL(device_destroy); | 1205 | EXPORT_SYMBOL_GPL(device_destroy); |
1184 | 1206 | ||
1207 | #ifdef CONFIG_PM_SLEEP | ||
1208 | /** | ||
1209 | * destroy_suspended_device - asks the PM core to remove a suspended device | ||
1210 | * @class: pointer to the struct class that this device was registered with | ||
1211 | * @devt: the dev_t of the device that was previously registered | ||
1212 | * | ||
1213 | * This call notifies the PM core of the necessity to unregister a suspended | ||
1214 | * device created with a call to device_create() (devices cannot be | ||
1215 | * unregistered directly while suspended, since the PM core holds their | ||
1216 | * semaphores at that time). | ||
1217 | * | ||
1218 | * It can only be called within the scope of a system sleep transition. In | ||
1219 | * practice this means it has to be directly or indirectly invoked either by | ||
1220 | * a suspend or resume method, or by the PM core (e.g. via | ||
1221 | * disable_nonboot_cpus() or enable_nonboot_cpus()). | ||
1222 | */ | ||
1223 | void destroy_suspended_device(struct class *class, dev_t devt) | ||
1224 | { | ||
1225 | struct device *dev; | ||
1226 | |||
1227 | dev = find_device(class, devt); | ||
1228 | if (dev) | ||
1229 | device_pm_schedule_removal(dev); | ||
1230 | } | ||
1231 | EXPORT_SYMBOL_GPL(destroy_suspended_device); | ||
1232 | #endif /* CONFIG_PM_SLEEP */ | ||
1233 | |||
1185 | /** | 1234 | /** |
1186 | * device_rename - renames a device | 1235 | * device_rename - renames a device |
1187 | * @dev: the pointer to the struct device to be renamed | 1236 | * @dev: the pointer to the struct device to be renamed |