diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-10 17:14:53 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-10 17:14:53 -0400 |
commit | 85fb0a1c35d86ed9a4de8d6cba79ba0801f7a1f7 (patch) | |
tree | 4373e14df0aa4064e64cf318edd3e07f5e162270 | |
parent | a9238741987386bb549d61572973c7e62b2a4145 (diff) | |
parent | 942f40155a743f4204308d62405dacaa4bfadb11 (diff) |
Merge branch 'acpi-hotplug'
* acpi-hotplug:
PM / hibernate / memory hotplug: Rework mutual exclusion
PM / hibernate: Create memory bitmaps after freezing user space
ACPI / scan: Change ordering of locks for device hotplug
-rw-r--r-- | drivers/acpi/scan.c | 15 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 45 | ||||
-rw-r--r-- | kernel/power/user.c | 24 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 4 |
4 files changed, 43 insertions, 45 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 61d090b6ce25..fbdb82e70d10 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -204,8 +204,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
204 | return -EINVAL; | 204 | return -EINVAL; |
205 | } | 205 | } |
206 | 206 | ||
207 | lock_device_hotplug(); | ||
208 | |||
209 | /* | 207 | /* |
210 | * Carry out two passes here and ignore errors in the first pass, | 208 | * Carry out two passes here and ignore errors in the first pass, |
211 | * because if the devices in question are memory blocks and | 209 | * because if the devices in question are memory blocks and |
@@ -236,9 +234,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
236 | ACPI_UINT32_MAX, | 234 | ACPI_UINT32_MAX, |
237 | acpi_bus_online_companions, NULL, | 235 | acpi_bus_online_companions, NULL, |
238 | NULL, NULL); | 236 | NULL, NULL); |
239 | |||
240 | unlock_device_hotplug(); | ||
241 | |||
242 | put_device(&device->dev); | 237 | put_device(&device->dev); |
243 | return -EBUSY; | 238 | return -EBUSY; |
244 | } | 239 | } |
@@ -249,8 +244,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
249 | 244 | ||
250 | acpi_bus_trim(device); | 245 | acpi_bus_trim(device); |
251 | 246 | ||
252 | unlock_device_hotplug(); | ||
253 | |||
254 | /* Device node has been unregistered. */ | 247 | /* Device node has been unregistered. */ |
255 | put_device(&device->dev); | 248 | put_device(&device->dev); |
256 | device = NULL; | 249 | device = NULL; |
@@ -289,6 +282,7 @@ static void acpi_bus_device_eject(void *context) | |||
289 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 282 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
290 | int error; | 283 | int error; |
291 | 284 | ||
285 | lock_device_hotplug(); | ||
292 | mutex_lock(&acpi_scan_lock); | 286 | mutex_lock(&acpi_scan_lock); |
293 | 287 | ||
294 | acpi_bus_get_device(handle, &device); | 288 | acpi_bus_get_device(handle, &device); |
@@ -312,6 +306,7 @@ static void acpi_bus_device_eject(void *context) | |||
312 | 306 | ||
313 | out: | 307 | out: |
314 | mutex_unlock(&acpi_scan_lock); | 308 | mutex_unlock(&acpi_scan_lock); |
309 | unlock_device_hotplug(); | ||
315 | return; | 310 | return; |
316 | 311 | ||
317 | err_out: | 312 | err_out: |
@@ -326,8 +321,8 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | |||
326 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 321 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
327 | int error; | 322 | int error; |
328 | 323 | ||
329 | mutex_lock(&acpi_scan_lock); | ||
330 | lock_device_hotplug(); | 324 | lock_device_hotplug(); |
325 | mutex_lock(&acpi_scan_lock); | ||
331 | 326 | ||
332 | if (ost_source != ACPI_NOTIFY_BUS_CHECK) { | 327 | if (ost_source != ACPI_NOTIFY_BUS_CHECK) { |
333 | acpi_bus_get_device(handle, &device); | 328 | acpi_bus_get_device(handle, &device); |
@@ -353,9 +348,9 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | |||
353 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | 348 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); |
354 | 349 | ||
355 | out: | 350 | out: |
356 | unlock_device_hotplug(); | ||
357 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); | 351 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); |
358 | mutex_unlock(&acpi_scan_lock); | 352 | mutex_unlock(&acpi_scan_lock); |
353 | unlock_device_hotplug(); | ||
359 | } | 354 | } |
360 | 355 | ||
361 | static void acpi_scan_bus_check(void *context) | 356 | static void acpi_scan_bus_check(void *context) |
@@ -446,6 +441,7 @@ void acpi_bus_hot_remove_device(void *context) | |||
446 | acpi_handle handle = device->handle; | 441 | acpi_handle handle = device->handle; |
447 | int error; | 442 | int error; |
448 | 443 | ||
444 | lock_device_hotplug(); | ||
449 | mutex_lock(&acpi_scan_lock); | 445 | mutex_lock(&acpi_scan_lock); |
450 | 446 | ||
451 | error = acpi_scan_hot_remove(device); | 447 | error = acpi_scan_hot_remove(device); |
@@ -455,6 +451,7 @@ void acpi_bus_hot_remove_device(void *context) | |||
455 | NULL); | 451 | NULL); |
456 | 452 | ||
457 | mutex_unlock(&acpi_scan_lock); | 453 | mutex_unlock(&acpi_scan_lock); |
454 | unlock_device_hotplug(); | ||
458 | kfree(context); | 455 | kfree(context); |
459 | } | 456 | } |
460 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); | 457 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b26f5f1e773e..0b78f72ad39d 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -644,22 +644,23 @@ int hibernate(void) | |||
644 | if (error) | 644 | if (error) |
645 | goto Exit; | 645 | goto Exit; |
646 | 646 | ||
647 | /* Allocate memory management structures */ | ||
648 | error = create_basic_memory_bitmaps(); | ||
649 | if (error) | ||
650 | goto Exit; | ||
651 | |||
652 | printk(KERN_INFO "PM: Syncing filesystems ... "); | 647 | printk(KERN_INFO "PM: Syncing filesystems ... "); |
653 | sys_sync(); | 648 | sys_sync(); |
654 | printk("done.\n"); | 649 | printk("done.\n"); |
655 | 650 | ||
656 | error = freeze_processes(); | 651 | error = freeze_processes(); |
657 | if (error) | 652 | if (error) |
658 | goto Free_bitmaps; | 653 | goto Exit; |
654 | |||
655 | lock_device_hotplug(); | ||
656 | /* Allocate memory management structures */ | ||
657 | error = create_basic_memory_bitmaps(); | ||
658 | if (error) | ||
659 | goto Thaw; | ||
659 | 660 | ||
660 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | 661 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); |
661 | if (error || freezer_test_done) | 662 | if (error || freezer_test_done) |
662 | goto Thaw; | 663 | goto Free_bitmaps; |
663 | 664 | ||
664 | if (in_suspend) { | 665 | if (in_suspend) { |
665 | unsigned int flags = 0; | 666 | unsigned int flags = 0; |
@@ -682,14 +683,14 @@ int hibernate(void) | |||
682 | pr_debug("PM: Image restored successfully.\n"); | 683 | pr_debug("PM: Image restored successfully.\n"); |
683 | } | 684 | } |
684 | 685 | ||
686 | Free_bitmaps: | ||
687 | free_basic_memory_bitmaps(); | ||
685 | Thaw: | 688 | Thaw: |
689 | unlock_device_hotplug(); | ||
686 | thaw_processes(); | 690 | thaw_processes(); |
687 | 691 | ||
688 | /* Don't bother checking whether freezer_test_done is true */ | 692 | /* Don't bother checking whether freezer_test_done is true */ |
689 | freezer_test_done = false; | 693 | freezer_test_done = false; |
690 | |||
691 | Free_bitmaps: | ||
692 | free_basic_memory_bitmaps(); | ||
693 | Exit: | 694 | Exit: |
694 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 695 | pm_notifier_call_chain(PM_POST_HIBERNATION); |
695 | pm_restore_console(); | 696 | pm_restore_console(); |
@@ -806,21 +807,20 @@ static int software_resume(void) | |||
806 | pm_prepare_console(); | 807 | pm_prepare_console(); |
807 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | 808 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); |
808 | if (error) | 809 | if (error) |
809 | goto close_finish; | 810 | goto Close_Finish; |
810 | |||
811 | error = create_basic_memory_bitmaps(); | ||
812 | if (error) | ||
813 | goto close_finish; | ||
814 | 811 | ||
815 | pr_debug("PM: Preparing processes for restore.\n"); | 812 | pr_debug("PM: Preparing processes for restore.\n"); |
816 | error = freeze_processes(); | 813 | error = freeze_processes(); |
817 | if (error) { | 814 | if (error) |
818 | swsusp_close(FMODE_READ); | 815 | goto Close_Finish; |
819 | goto Done; | ||
820 | } | ||
821 | 816 | ||
822 | pr_debug("PM: Loading hibernation image.\n"); | 817 | pr_debug("PM: Loading hibernation image.\n"); |
823 | 818 | ||
819 | lock_device_hotplug(); | ||
820 | error = create_basic_memory_bitmaps(); | ||
821 | if (error) | ||
822 | goto Thaw; | ||
823 | |||
824 | error = swsusp_read(&flags); | 824 | error = swsusp_read(&flags); |
825 | swsusp_close(FMODE_READ); | 825 | swsusp_close(FMODE_READ); |
826 | if (!error) | 826 | if (!error) |
@@ -828,9 +828,10 @@ static int software_resume(void) | |||
828 | 828 | ||
829 | printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); | 829 | printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); |
830 | swsusp_free(); | 830 | swsusp_free(); |
831 | thaw_processes(); | ||
832 | Done: | ||
833 | free_basic_memory_bitmaps(); | 831 | free_basic_memory_bitmaps(); |
832 | Thaw: | ||
833 | unlock_device_hotplug(); | ||
834 | thaw_processes(); | ||
834 | Finish: | 835 | Finish: |
835 | pm_notifier_call_chain(PM_POST_RESTORE); | 836 | pm_notifier_call_chain(PM_POST_RESTORE); |
836 | pm_restore_console(); | 837 | pm_restore_console(); |
@@ -840,7 +841,7 @@ static int software_resume(void) | |||
840 | mutex_unlock(&pm_mutex); | 841 | mutex_unlock(&pm_mutex); |
841 | pr_debug("PM: Hibernation image not present or could not be loaded.\n"); | 842 | pr_debug("PM: Hibernation image not present or could not be loaded.\n"); |
842 | return error; | 843 | return error; |
843 | close_finish: | 844 | Close_Finish: |
844 | swsusp_close(FMODE_READ); | 845 | swsusp_close(FMODE_READ); |
845 | goto Finish; | 846 | goto Finish; |
846 | } | 847 | } |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 4ed81e74f86f..72e8f4fd616d 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -60,11 +60,6 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
60 | error = -ENOSYS; | 60 | error = -ENOSYS; |
61 | goto Unlock; | 61 | goto Unlock; |
62 | } | 62 | } |
63 | if(create_basic_memory_bitmaps()) { | ||
64 | atomic_inc(&snapshot_device_available); | ||
65 | error = -ENOMEM; | ||
66 | goto Unlock; | ||
67 | } | ||
68 | nonseekable_open(inode, filp); | 63 | nonseekable_open(inode, filp); |
69 | data = &snapshot_state; | 64 | data = &snapshot_state; |
70 | filp->private_data = data; | 65 | filp->private_data = data; |
@@ -90,10 +85,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
90 | if (error) | 85 | if (error) |
91 | pm_notifier_call_chain(PM_POST_RESTORE); | 86 | pm_notifier_call_chain(PM_POST_RESTORE); |
92 | } | 87 | } |
93 | if (error) { | 88 | if (error) |
94 | free_basic_memory_bitmaps(); | ||
95 | atomic_inc(&snapshot_device_available); | 89 | atomic_inc(&snapshot_device_available); |
96 | } | 90 | |
97 | data->frozen = 0; | 91 | data->frozen = 0; |
98 | data->ready = 0; | 92 | data->ready = 0; |
99 | data->platform_support = 0; | 93 | data->platform_support = 0; |
@@ -111,11 +105,11 @@ static int snapshot_release(struct inode *inode, struct file *filp) | |||
111 | lock_system_sleep(); | 105 | lock_system_sleep(); |
112 | 106 | ||
113 | swsusp_free(); | 107 | swsusp_free(); |
114 | free_basic_memory_bitmaps(); | ||
115 | data = filp->private_data; | 108 | data = filp->private_data; |
116 | free_all_swap_pages(data->swap); | 109 | free_all_swap_pages(data->swap); |
117 | if (data->frozen) { | 110 | if (data->frozen) { |
118 | pm_restore_gfp_mask(); | 111 | pm_restore_gfp_mask(); |
112 | free_basic_memory_bitmaps(); | ||
119 | thaw_processes(); | 113 | thaw_processes(); |
120 | } | 114 | } |
121 | pm_notifier_call_chain(data->mode == O_RDONLY ? | 115 | pm_notifier_call_chain(data->mode == O_RDONLY ? |
@@ -207,6 +201,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |||
207 | if (!mutex_trylock(&pm_mutex)) | 201 | if (!mutex_trylock(&pm_mutex)) |
208 | return -EBUSY; | 202 | return -EBUSY; |
209 | 203 | ||
204 | lock_device_hotplug(); | ||
210 | data = filp->private_data; | 205 | data = filp->private_data; |
211 | 206 | ||
212 | switch (cmd) { | 207 | switch (cmd) { |
@@ -220,14 +215,22 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |||
220 | printk("done.\n"); | 215 | printk("done.\n"); |
221 | 216 | ||
222 | error = freeze_processes(); | 217 | error = freeze_processes(); |
223 | if (!error) | 218 | if (error) |
219 | break; | ||
220 | |||
221 | error = create_basic_memory_bitmaps(); | ||
222 | if (error) | ||
223 | thaw_processes(); | ||
224 | else | ||
224 | data->frozen = 1; | 225 | data->frozen = 1; |
226 | |||
225 | break; | 227 | break; |
226 | 228 | ||
227 | case SNAPSHOT_UNFREEZE: | 229 | case SNAPSHOT_UNFREEZE: |
228 | if (!data->frozen || data->ready) | 230 | if (!data->frozen || data->ready) |
229 | break; | 231 | break; |
230 | pm_restore_gfp_mask(); | 232 | pm_restore_gfp_mask(); |
233 | free_basic_memory_bitmaps(); | ||
231 | thaw_processes(); | 234 | thaw_processes(); |
232 | data->frozen = 0; | 235 | data->frozen = 0; |
233 | break; | 236 | break; |
@@ -371,6 +374,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |||
371 | 374 | ||
372 | } | 375 | } |
373 | 376 | ||
377 | unlock_device_hotplug(); | ||
374 | mutex_unlock(&pm_mutex); | 378 | mutex_unlock(&pm_mutex); |
375 | 379 | ||
376 | return error; | 380 | return error; |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index ca1dd3aa5eee..53ad1325d7a7 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -51,14 +51,10 @@ DEFINE_MUTEX(mem_hotplug_mutex); | |||
51 | void lock_memory_hotplug(void) | 51 | void lock_memory_hotplug(void) |
52 | { | 52 | { |
53 | mutex_lock(&mem_hotplug_mutex); | 53 | mutex_lock(&mem_hotplug_mutex); |
54 | |||
55 | /* for exclusive hibernation if CONFIG_HIBERNATION=y */ | ||
56 | lock_system_sleep(); | ||
57 | } | 54 | } |
58 | 55 | ||
59 | void unlock_memory_hotplug(void) | 56 | void unlock_memory_hotplug(void) |
60 | { | 57 | { |
61 | unlock_system_sleep(); | ||
62 | mutex_unlock(&mem_hotplug_mutex); | 58 | mutex_unlock(&mem_hotplug_mutex); |
63 | } | 59 | } |
64 | 60 | ||