diff options
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/Kconfig | 10 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 58 | ||||
-rw-r--r-- | kernel/power/main.c | 1 | ||||
-rw-r--r-- | kernel/power/power.h | 4 | ||||
-rw-r--r-- | kernel/power/snapshot.c | 33 | ||||
-rw-r--r-- | kernel/power/suspend.c | 14 | ||||
-rw-r--r-- | kernel/power/user.c | 5 |
7 files changed, 79 insertions, 46 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 6de9a8fc3417..87f4d24b55b0 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -125,12 +125,6 @@ config PM_DEBUG | |||
125 | code. This is helpful when debugging and reporting PM bugs, like | 125 | code. This is helpful when debugging and reporting PM bugs, like |
126 | suspend support. | 126 | suspend support. |
127 | 127 | ||
128 | config PM_VERBOSE | ||
129 | bool "Verbose Power Management debugging" | ||
130 | depends on PM_DEBUG | ||
131 | ---help--- | ||
132 | This option enables verbose messages from the Power Management code. | ||
133 | |||
134 | config PM_ADVANCED_DEBUG | 128 | config PM_ADVANCED_DEBUG |
135 | bool "Extra PM attributes in sysfs for low-level debugging/testing" | 129 | bool "Extra PM attributes in sysfs for low-level debugging/testing" |
136 | depends on PM_DEBUG | 130 | depends on PM_DEBUG |
@@ -229,3 +223,7 @@ config PM_OPP | |||
229 | representing individual voltage domains and provides SOC | 223 | representing individual voltage domains and provides SOC |
230 | implementations a ready to use framework to manage OPPs. | 224 | implementations a ready to use framework to manage OPPs. |
231 | For more information, read <file:Documentation/power/opp.txt> | 225 | For more information, read <file:Documentation/power/opp.txt> |
226 | |||
227 | config PM_RUNTIME_CLK | ||
228 | def_bool y | ||
229 | depends on PM_RUNTIME && HAVE_CLK | ||
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 50aae660174d..f9bec56d8825 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -272,12 +272,7 @@ static int create_image(int platform_mode) | |||
272 | 272 | ||
273 | local_irq_disable(); | 273 | local_irq_disable(); |
274 | 274 | ||
275 | error = sysdev_suspend(PMSG_FREEZE); | 275 | error = syscore_suspend(); |
276 | if (!error) { | ||
277 | error = syscore_suspend(); | ||
278 | if (error) | ||
279 | sysdev_resume(); | ||
280 | } | ||
281 | if (error) { | 276 | if (error) { |
282 | printk(KERN_ERR "PM: Some system devices failed to power down, " | 277 | printk(KERN_ERR "PM: Some system devices failed to power down, " |
283 | "aborting hibernation\n"); | 278 | "aborting hibernation\n"); |
@@ -302,7 +297,6 @@ static int create_image(int platform_mode) | |||
302 | 297 | ||
303 | Power_up: | 298 | Power_up: |
304 | syscore_resume(); | 299 | syscore_resume(); |
305 | sysdev_resume(); | ||
306 | /* NOTE: dpm_resume_noirq() is just a resume() for devices | 300 | /* NOTE: dpm_resume_noirq() is just a resume() for devices |
307 | * that suspended with irqs off ... no overall powerup. | 301 | * that suspended with irqs off ... no overall powerup. |
308 | */ | 302 | */ |
@@ -333,20 +327,25 @@ static int create_image(int platform_mode) | |||
333 | 327 | ||
334 | int hibernation_snapshot(int platform_mode) | 328 | int hibernation_snapshot(int platform_mode) |
335 | { | 329 | { |
330 | pm_message_t msg = PMSG_RECOVER; | ||
336 | int error; | 331 | int error; |
337 | 332 | ||
338 | error = platform_begin(platform_mode); | 333 | error = platform_begin(platform_mode); |
339 | if (error) | 334 | if (error) |
340 | goto Close; | 335 | goto Close; |
341 | 336 | ||
337 | error = dpm_prepare(PMSG_FREEZE); | ||
338 | if (error) | ||
339 | goto Complete_devices; | ||
340 | |||
342 | /* Preallocate image memory before shutting down devices. */ | 341 | /* Preallocate image memory before shutting down devices. */ |
343 | error = hibernate_preallocate_memory(); | 342 | error = hibernate_preallocate_memory(); |
344 | if (error) | 343 | if (error) |
345 | goto Close; | 344 | goto Complete_devices; |
346 | 345 | ||
347 | suspend_console(); | 346 | suspend_console(); |
348 | pm_restrict_gfp_mask(); | 347 | pm_restrict_gfp_mask(); |
349 | error = dpm_suspend_start(PMSG_FREEZE); | 348 | error = dpm_suspend(PMSG_FREEZE); |
350 | if (error) | 349 | if (error) |
351 | goto Recover_platform; | 350 | goto Recover_platform; |
352 | 351 | ||
@@ -364,13 +363,17 @@ int hibernation_snapshot(int platform_mode) | |||
364 | if (error || !in_suspend) | 363 | if (error || !in_suspend) |
365 | swsusp_free(); | 364 | swsusp_free(); |
366 | 365 | ||
367 | dpm_resume_end(in_suspend ? | 366 | msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; |
368 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 367 | dpm_resume(msg); |
369 | 368 | ||
370 | if (error || !in_suspend) | 369 | if (error || !in_suspend) |
371 | pm_restore_gfp_mask(); | 370 | pm_restore_gfp_mask(); |
372 | 371 | ||
373 | resume_console(); | 372 | resume_console(); |
373 | |||
374 | Complete_devices: | ||
375 | dpm_complete(msg); | ||
376 | |||
374 | Close: | 377 | Close: |
375 | platform_end(platform_mode); | 378 | platform_end(platform_mode); |
376 | return error; | 379 | return error; |
@@ -409,12 +412,7 @@ static int resume_target_kernel(bool platform_mode) | |||
409 | 412 | ||
410 | local_irq_disable(); | 413 | local_irq_disable(); |
411 | 414 | ||
412 | error = sysdev_suspend(PMSG_QUIESCE); | 415 | error = syscore_suspend(); |
413 | if (!error) { | ||
414 | error = syscore_suspend(); | ||
415 | if (error) | ||
416 | sysdev_resume(); | ||
417 | } | ||
418 | if (error) | 416 | if (error) |
419 | goto Enable_irqs; | 417 | goto Enable_irqs; |
420 | 418 | ||
@@ -442,7 +440,6 @@ static int resume_target_kernel(bool platform_mode) | |||
442 | touch_softlockup_watchdog(); | 440 | touch_softlockup_watchdog(); |
443 | 441 | ||
444 | syscore_resume(); | 442 | syscore_resume(); |
445 | sysdev_resume(); | ||
446 | 443 | ||
447 | Enable_irqs: | 444 | Enable_irqs: |
448 | local_irq_enable(); | 445 | local_irq_enable(); |
@@ -528,7 +525,6 @@ int hibernation_platform_enter(void) | |||
528 | goto Platform_finish; | 525 | goto Platform_finish; |
529 | 526 | ||
530 | local_irq_disable(); | 527 | local_irq_disable(); |
531 | sysdev_suspend(PMSG_HIBERNATE); | ||
532 | syscore_suspend(); | 528 | syscore_suspend(); |
533 | if (pm_wakeup_pending()) { | 529 | if (pm_wakeup_pending()) { |
534 | error = -EAGAIN; | 530 | error = -EAGAIN; |
@@ -541,7 +537,6 @@ int hibernation_platform_enter(void) | |||
541 | 537 | ||
542 | Power_up: | 538 | Power_up: |
543 | syscore_resume(); | 539 | syscore_resume(); |
544 | sysdev_resume(); | ||
545 | local_irq_enable(); | 540 | local_irq_enable(); |
546 | enable_nonboot_cpus(); | 541 | enable_nonboot_cpus(); |
547 | 542 | ||
@@ -982,10 +977,33 @@ static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *att | |||
982 | 977 | ||
983 | power_attr(image_size); | 978 | power_attr(image_size); |
984 | 979 | ||
980 | static ssize_t reserved_size_show(struct kobject *kobj, | ||
981 | struct kobj_attribute *attr, char *buf) | ||
982 | { | ||
983 | return sprintf(buf, "%lu\n", reserved_size); | ||
984 | } | ||
985 | |||
986 | static ssize_t reserved_size_store(struct kobject *kobj, | ||
987 | struct kobj_attribute *attr, | ||
988 | const char *buf, size_t n) | ||
989 | { | ||
990 | unsigned long size; | ||
991 | |||
992 | if (sscanf(buf, "%lu", &size) == 1) { | ||
993 | reserved_size = size; | ||
994 | return n; | ||
995 | } | ||
996 | |||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
1000 | power_attr(reserved_size); | ||
1001 | |||
985 | static struct attribute * g[] = { | 1002 | static struct attribute * g[] = { |
986 | &disk_attr.attr, | 1003 | &disk_attr.attr, |
987 | &resume_attr.attr, | 1004 | &resume_attr.attr, |
988 | &image_size_attr.attr, | 1005 | &image_size_attr.attr, |
1006 | &reserved_size_attr.attr, | ||
989 | NULL, | 1007 | NULL, |
990 | }; | 1008 | }; |
991 | 1009 | ||
diff --git a/kernel/power/main.c b/kernel/power/main.c index de9aef8742f4..2981af4ce7cb 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -337,6 +337,7 @@ static int __init pm_init(void) | |||
337 | if (error) | 337 | if (error) |
338 | return error; | 338 | return error; |
339 | hibernate_image_size_init(); | 339 | hibernate_image_size_init(); |
340 | hibernate_reserved_size_init(); | ||
340 | power_kobj = kobject_create_and_add("power", NULL); | 341 | power_kobj = kobject_create_and_add("power", NULL); |
341 | if (!power_kobj) | 342 | if (!power_kobj) |
342 | return -ENOMEM; | 343 | return -ENOMEM; |
diff --git a/kernel/power/power.h b/kernel/power/power.h index 03634be55f62..9a00a0a26280 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -15,6 +15,7 @@ struct swsusp_info { | |||
15 | 15 | ||
16 | #ifdef CONFIG_HIBERNATION | 16 | #ifdef CONFIG_HIBERNATION |
17 | /* kernel/power/snapshot.c */ | 17 | /* kernel/power/snapshot.c */ |
18 | extern void __init hibernate_reserved_size_init(void); | ||
18 | extern void __init hibernate_image_size_init(void); | 19 | extern void __init hibernate_image_size_init(void); |
19 | 20 | ||
20 | #ifdef CONFIG_ARCH_HIBERNATION_HEADER | 21 | #ifdef CONFIG_ARCH_HIBERNATION_HEADER |
@@ -55,6 +56,7 @@ extern int hibernation_platform_enter(void); | |||
55 | 56 | ||
56 | #else /* !CONFIG_HIBERNATION */ | 57 | #else /* !CONFIG_HIBERNATION */ |
57 | 58 | ||
59 | static inline void hibernate_reserved_size_init(void) {} | ||
58 | static inline void hibernate_image_size_init(void) {} | 60 | static inline void hibernate_image_size_init(void) {} |
59 | #endif /* !CONFIG_HIBERNATION */ | 61 | #endif /* !CONFIG_HIBERNATION */ |
60 | 62 | ||
@@ -72,6 +74,8 @@ static struct kobj_attribute _name##_attr = { \ | |||
72 | 74 | ||
73 | /* Preferred image size in bytes (default 500 MB) */ | 75 | /* Preferred image size in bytes (default 500 MB) */ |
74 | extern unsigned long image_size; | 76 | extern unsigned long image_size; |
77 | /* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */ | ||
78 | extern unsigned long reserved_size; | ||
75 | extern int in_suspend; | 79 | extern int in_suspend; |
76 | extern dev_t swsusp_resume_device; | 80 | extern dev_t swsusp_resume_device; |
77 | extern sector_t swsusp_resume_block; | 81 | extern sector_t swsusp_resume_block; |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index ca0aacc24874..ace55889f702 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -41,16 +41,28 @@ static void swsusp_set_page_forbidden(struct page *); | |||
41 | static void swsusp_unset_page_forbidden(struct page *); | 41 | static void swsusp_unset_page_forbidden(struct page *); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Number of bytes to reserve for memory allocations made by device drivers | ||
45 | * from their ->freeze() and ->freeze_noirq() callbacks so that they don't | ||
46 | * cause image creation to fail (tunable via /sys/power/reserved_size). | ||
47 | */ | ||
48 | unsigned long reserved_size; | ||
49 | |||
50 | void __init hibernate_reserved_size_init(void) | ||
51 | { | ||
52 | reserved_size = SPARE_PAGES * PAGE_SIZE; | ||
53 | } | ||
54 | |||
55 | /* | ||
44 | * Preferred image size in bytes (tunable via /sys/power/image_size). | 56 | * Preferred image size in bytes (tunable via /sys/power/image_size). |
45 | * When it is set to N, the image creating code will do its best to | 57 | * When it is set to N, swsusp will do its best to ensure the image |
46 | * ensure the image size will not exceed N bytes, but if that is | 58 | * size will not exceed N bytes, but if that is impossible, it will |
47 | * impossible, it will try to create the smallest image possible. | 59 | * try to create the smallest image possible. |
48 | */ | 60 | */ |
49 | unsigned long image_size; | 61 | unsigned long image_size; |
50 | 62 | ||
51 | void __init hibernate_image_size_init(void) | 63 | void __init hibernate_image_size_init(void) |
52 | { | 64 | { |
53 | image_size = (totalram_pages / 3) * PAGE_SIZE; | 65 | image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE; |
54 | } | 66 | } |
55 | 67 | ||
56 | /* List of PBEs needed for restoring the pages that were allocated before | 68 | /* List of PBEs needed for restoring the pages that were allocated before |
@@ -1263,11 +1275,13 @@ static unsigned long minimum_image_size(unsigned long saveable) | |||
1263 | * frame in use. We also need a number of page frames to be free during | 1275 | * frame in use. We also need a number of page frames to be free during |
1264 | * hibernation for allocations made while saving the image and for device | 1276 | * hibernation for allocations made while saving the image and for device |
1265 | * drivers, in case they need to allocate memory from their hibernation | 1277 | * drivers, in case they need to allocate memory from their hibernation |
1266 | * callbacks (these two numbers are given by PAGES_FOR_IO and SPARE_PAGES, | 1278 | * callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough |
1267 | * respectively, both of which are rough estimates). To make this happen, we | 1279 | * estimate) and reserverd_size divided by PAGE_SIZE (which is tunable through |
1268 | * compute the total number of available page frames and allocate at least | 1280 | * /sys/power/reserved_size, respectively). To make this happen, we compute the |
1281 | * total number of available page frames and allocate at least | ||
1269 | * | 1282 | * |
1270 | * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 + 2 * SPARE_PAGES | 1283 | * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 |
1284 | * + 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE) | ||
1271 | * | 1285 | * |
1272 | * of them, which corresponds to the maximum size of a hibernation image. | 1286 | * of them, which corresponds to the maximum size of a hibernation image. |
1273 | * | 1287 | * |
@@ -1322,7 +1336,8 @@ int hibernate_preallocate_memory(void) | |||
1322 | count -= totalreserve_pages; | 1336 | count -= totalreserve_pages; |
1323 | 1337 | ||
1324 | /* Compute the maximum number of saveable pages to leave in memory. */ | 1338 | /* Compute the maximum number of saveable pages to leave in memory. */ |
1325 | max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES; | 1339 | max_size = (count - (size + PAGES_FOR_IO)) / 2 |
1340 | - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE); | ||
1326 | /* Compute the desired number of image pages specified by image_size. */ | 1341 | /* Compute the desired number of image pages specified by image_size. */ |
1327 | size = DIV_ROUND_UP(image_size, PAGE_SIZE); | 1342 | size = DIV_ROUND_UP(image_size, PAGE_SIZE); |
1328 | if (size > max_size) | 1343 | if (size > max_size) |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 8935369d503a..1c41ba215419 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -163,19 +163,13 @@ static int suspend_enter(suspend_state_t state) | |||
163 | arch_suspend_disable_irqs(); | 163 | arch_suspend_disable_irqs(); |
164 | BUG_ON(!irqs_disabled()); | 164 | BUG_ON(!irqs_disabled()); |
165 | 165 | ||
166 | error = sysdev_suspend(PMSG_SUSPEND); | 166 | error = syscore_suspend(); |
167 | if (!error) { | ||
168 | error = syscore_suspend(); | ||
169 | if (error) | ||
170 | sysdev_resume(); | ||
171 | } | ||
172 | if (!error) { | 167 | if (!error) { |
173 | if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { | 168 | if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { |
174 | error = suspend_ops->enter(state); | 169 | error = suspend_ops->enter(state); |
175 | events_check_enabled = false; | 170 | events_check_enabled = false; |
176 | } | 171 | } |
177 | syscore_resume(); | 172 | syscore_resume(); |
178 | sysdev_resume(); | ||
179 | } | 173 | } |
180 | 174 | ||
181 | arch_suspend_enable_irqs(); | 175 | arch_suspend_enable_irqs(); |
@@ -216,7 +210,6 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
216 | goto Close; | 210 | goto Close; |
217 | } | 211 | } |
218 | suspend_console(); | 212 | suspend_console(); |
219 | pm_restrict_gfp_mask(); | ||
220 | suspend_test_start(); | 213 | suspend_test_start(); |
221 | error = dpm_suspend_start(PMSG_SUSPEND); | 214 | error = dpm_suspend_start(PMSG_SUSPEND); |
222 | if (error) { | 215 | if (error) { |
@@ -227,13 +220,12 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
227 | if (suspend_test(TEST_DEVICES)) | 220 | if (suspend_test(TEST_DEVICES)) |
228 | goto Recover_platform; | 221 | goto Recover_platform; |
229 | 222 | ||
230 | suspend_enter(state); | 223 | error = suspend_enter(state); |
231 | 224 | ||
232 | Resume_devices: | 225 | Resume_devices: |
233 | suspend_test_start(); | 226 | suspend_test_start(); |
234 | dpm_resume_end(PMSG_RESUME); | 227 | dpm_resume_end(PMSG_RESUME); |
235 | suspend_test_finish("resume devices"); | 228 | suspend_test_finish("resume devices"); |
236 | pm_restore_gfp_mask(); | ||
237 | resume_console(); | 229 | resume_console(); |
238 | Close: | 230 | Close: |
239 | if (suspend_ops->end) | 231 | if (suspend_ops->end) |
@@ -294,7 +286,9 @@ int enter_state(suspend_state_t state) | |||
294 | goto Finish; | 286 | goto Finish; |
295 | 287 | ||
296 | pr_debug("PM: Entering %s sleep\n", pm_states[state]); | 288 | pr_debug("PM: Entering %s sleep\n", pm_states[state]); |
289 | pm_restrict_gfp_mask(); | ||
297 | error = suspend_devices_and_enter(state); | 290 | error = suspend_devices_and_enter(state); |
291 | pm_restore_gfp_mask(); | ||
298 | 292 | ||
299 | Finish: | 293 | Finish: |
300 | pr_debug("PM: Finishing wakeup.\n"); | 294 | pr_debug("PM: Finishing wakeup.\n"); |
diff --git a/kernel/power/user.c b/kernel/power/user.c index c36c3b9e8a84..7d02d33be699 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -135,8 +135,10 @@ static int snapshot_release(struct inode *inode, struct file *filp) | |||
135 | free_basic_memory_bitmaps(); | 135 | free_basic_memory_bitmaps(); |
136 | data = filp->private_data; | 136 | data = filp->private_data; |
137 | free_all_swap_pages(data->swap); | 137 | free_all_swap_pages(data->swap); |
138 | if (data->frozen) | 138 | if (data->frozen) { |
139 | pm_restore_gfp_mask(); | ||
139 | thaw_processes(); | 140 | thaw_processes(); |
141 | } | ||
140 | pm_notifier_call_chain(data->mode == O_RDONLY ? | 142 | pm_notifier_call_chain(data->mode == O_RDONLY ? |
141 | PM_POST_HIBERNATION : PM_POST_RESTORE); | 143 | PM_POST_HIBERNATION : PM_POST_RESTORE); |
142 | atomic_inc(&snapshot_device_available); | 144 | atomic_inc(&snapshot_device_available); |
@@ -379,6 +381,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |||
379 | * PM_HIBERNATION_PREPARE | 381 | * PM_HIBERNATION_PREPARE |
380 | */ | 382 | */ |
381 | error = suspend_devices_and_enter(PM_SUSPEND_MEM); | 383 | error = suspend_devices_and_enter(PM_SUSPEND_MEM); |
384 | data->ready = 0; | ||
382 | break; | 385 | break; |
383 | 386 | ||
384 | case SNAPSHOT_PLATFORM_SUPPORT: | 387 | case SNAPSHOT_PLATFORM_SUPPORT: |