Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: Allow drivers to allocate memory from .prepare() callbacks safely

If device drivers allocate substantial amounts of memory (above 1 MB)
in their hibernate .freeze() callbacks (or in their legacy suspend
callbcks during hibernation), the subsequent creation of hibernate
image may fail due to the lack of memory. This is the case, because
the drivers' .freeze() callbacks are executed after the hibernate
memory preallocation has been carried out and the preallocated amount
of memory may be too small to cover the new driver allocations.
Unfortunately, the drivers' .prepare() callbacks also are executed
after the hibernate memory preallocation has completed, so they are
not suitable for allocating additional memory either. Thus the only
way a driver can safely allocate memory during hibernation is to use
a hibernate/suspend notifier. However, the notifiers are called
before the freezing of user space and the drivers wanting to use them
for allocating additional memory may not know how much memory needs
to be allocated at that point.

To let device drivers overcome this difficulty rework the hibernation
sequence so that the memory preallocation is carried out after the
drivers' .prepare() callbacks have been executed, so that the
.prepare() callbacks can be used for allocating additional memory
to be used by the drivers' .freeze() callbacks. Update documentation
to match the new behavior of the code.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

+59 -41
+9 -5
Documentation/power/devices.txt
··· 279 279 time.) Unlike the other suspend-related phases, during the prepare 280 280 phase the device tree is traversed top-down. 281 281 282 - The prepare phase uses only a bus callback. After the callback method 283 - returns, no new children may be registered below the device. The method 284 - may also prepare the device or driver in some way for the upcoming 285 - system power transition, but it should not put the device into a 286 - low-power state. 282 + In addition to that, if device drivers need to allocate additional 283 + memory to be able to hadle device suspend correctly, that should be 284 + done in the prepare phase. 285 + 286 + After the prepare callback method returns, no new children may be 287 + registered below the device. The method may also prepare the device or 288 + driver in some way for the upcoming system power transition (for 289 + example, by allocating additional memory required for this purpose), but 290 + it should not put the device into a low-power state. 287 291 288 292 2. The suspend methods should quiesce the device to stop it from performing 289 293 I/O. They also may save the device registers and put it into the
+21 -26
Documentation/power/notifiers.txt
··· 1 1 Suspend notifiers 2 - (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL 2 + (C) 2007-2011 Rafael J. Wysocki <rjw@sisk.pl>, GPL 3 3 4 - There are some operations that device drivers may want to carry out in their 5 - .suspend() routines, but shouldn't, because they can cause the hibernation or 6 - suspend to fail. For example, a driver may want to allocate a substantial amount 7 - of memory (like 50 MB) in .suspend(), but that shouldn't be done after the 8 - swsusp's memory shrinker has run. 4 + There are some operations that subsystems or drivers may want to carry out 5 + before hibernation/suspend or after restore/resume, but they require the system 6 + to be fully functional, so the drivers' and subsystems' .suspend() and .resume() 7 + or even .prepare() and .complete() callbacks are not suitable for this purpose. 8 + For example, device drivers may want to upload firmware to their devices after 9 + resume/restore, but they cannot do it by calling request_firmware() from their 10 + .resume() or .complete() routines (user land processes are frozen at these 11 + points). The solution may be to load the firmware into memory before processes 12 + are frozen and upload it from there in the .resume() routine. 13 + A suspend/hibernation notifier may be used for this purpose. 9 14 10 - Also, there may be some operations, that subsystems want to carry out before a 11 - hibernation/suspend or after a restore/resume, requiring the system to be fully 12 - functional, so the drivers' .suspend() and .resume() routines are not suitable 13 - for this purpose. For example, device drivers may want to upload firmware to 14 - their devices after a restore from a hibernation image, but they cannot do it by 15 - calling request_firmware() from their .resume() routines (user land processes 16 - are frozen at this point). The solution may be to load the firmware into 17 - memory before processes are frozen and upload it from there in the .resume() 18 - routine. Of course, a hibernation notifier may be used for this purpose. 19 - 20 - The subsystems that have such needs can register suspend notifiers that will be 21 - called upon the following events by the suspend core: 15 + The subsystems or drivers having such needs can register suspend notifiers that 16 + will be called upon the following events by the PM core: 22 17 23 18 PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will 24 19 be frozen immediately. 25 20 26 21 PM_POST_HIBERNATION The system memory state has been restored from a 27 - hibernation image or an error occurred during the 28 - hibernation. Device drivers' .resume() callbacks have 22 + hibernation image or an error occurred during 23 + hibernation. Device drivers' restore callbacks have 29 24 been executed and tasks have been thawed. 30 25 31 26 PM_RESTORE_PREPARE The system is going to restore a hibernation image. 32 - If all goes well the restored kernel will issue a 27 + If all goes well, the restored kernel will issue a 33 28 PM_POST_HIBERNATION notification. 34 29 35 - PM_POST_RESTORE An error occurred during the hibernation restore. 36 - Device drivers' .resume() callbacks have been executed 30 + PM_POST_RESTORE An error occurred during restore from hibernation. 31 + Device drivers' restore callbacks have been executed 37 32 and tasks have been thawed. 38 33 39 - PM_SUSPEND_PREPARE The system is preparing for a suspend. 34 + PM_SUSPEND_PREPARE The system is preparing for suspend. 40 35 41 36 PM_POST_SUSPEND The system has just resumed or an error occurred during 42 - the suspend. Device drivers' .resume() callbacks have 43 - been executed and tasks have been thawed. 37 + suspend. Device drivers' resume callbacks have been 38 + executed and tasks have been thawed. 44 39 45 40 It is generally assumed that whatever the notifiers do for 46 41 PM_HIBERNATION_PREPARE, should be undone for PM_POST_HIBERNATION. Analogously,
+12 -6
drivers/base/power/main.c
··· 579 579 * Execute the appropriate "resume" callback for all devices whose status 580 580 * indicates that they are suspended. 581 581 */ 582 - static void dpm_resume(pm_message_t state) 582 + void dpm_resume(pm_message_t state) 583 583 { 584 584 struct device *dev; 585 585 ktime_t starttime = ktime_get(); 586 + 587 + might_sleep(); 586 588 587 589 mutex_lock(&dpm_list_mtx); 588 590 pm_transition = state; ··· 658 656 * Execute the ->complete() callbacks for all devices whose PM status is not 659 657 * DPM_ON (this allows new devices to be registered). 660 658 */ 661 - static void dpm_complete(pm_message_t state) 659 + void dpm_complete(pm_message_t state) 662 660 { 663 661 struct list_head list; 662 + 663 + might_sleep(); 664 664 665 665 INIT_LIST_HEAD(&list); 666 666 mutex_lock(&dpm_list_mtx); ··· 692 688 */ 693 689 void dpm_resume_end(pm_message_t state) 694 690 { 695 - might_sleep(); 696 691 dpm_resume(state); 697 692 dpm_complete(state); 698 693 } ··· 915 912 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices. 916 913 * @state: PM transition of the system being carried out. 917 914 */ 918 - static int dpm_suspend(pm_message_t state) 915 + int dpm_suspend(pm_message_t state) 919 916 { 920 917 ktime_t starttime = ktime_get(); 921 918 int error = 0; 919 + 920 + might_sleep(); 922 921 923 922 mutex_lock(&dpm_list_mtx); 924 923 pm_transition = state; ··· 1008 1003 * 1009 1004 * Execute the ->prepare() callback(s) for all devices. 1010 1005 */ 1011 - static int dpm_prepare(pm_message_t state) 1006 + int dpm_prepare(pm_message_t state) 1012 1007 { 1013 1008 int error = 0; 1009 + 1010 + might_sleep(); 1014 1011 1015 1012 mutex_lock(&dpm_list_mtx); 1016 1013 while (!list_empty(&dpm_list)) { ··· 1062 1055 { 1063 1056 int error; 1064 1057 1065 - might_sleep(); 1066 1058 error = dpm_prepare(state); 1067 1059 if (!error) 1068 1060 error = dpm_suspend(state);
+4
include/linux/pm.h
··· 533 533 extern void device_pm_lock(void); 534 534 extern void dpm_resume_noirq(pm_message_t state); 535 535 extern void dpm_resume_end(pm_message_t state); 536 + extern void dpm_resume(pm_message_t state); 537 + extern void dpm_complete(pm_message_t state); 536 538 537 539 extern void device_pm_unlock(void); 538 540 extern int dpm_suspend_noirq(pm_message_t state); 539 541 extern int dpm_suspend_start(pm_message_t state); 542 + extern int dpm_suspend(pm_message_t state); 543 + extern int dpm_prepare(pm_message_t state); 540 544 541 545 extern void __suspend_report_result(const char *function, void *fn, int ret); 542 546
+13 -4
kernel/power/hibernate.c
··· 327 327 328 328 int hibernation_snapshot(int platform_mode) 329 329 { 330 + pm_message_t msg = PMSG_RECOVER; 330 331 int error; 331 332 332 333 error = platform_begin(platform_mode); 333 334 if (error) 334 335 goto Close; 335 336 337 + error = dpm_prepare(PMSG_FREEZE); 338 + if (error) 339 + goto Complete_devices; 340 + 336 341 /* Preallocate image memory before shutting down devices. */ 337 342 error = hibernate_preallocate_memory(); 338 343 if (error) 339 - goto Close; 344 + goto Complete_devices; 340 345 341 346 suspend_console(); 342 347 pm_restrict_gfp_mask(); 343 - error = dpm_suspend_start(PMSG_FREEZE); 348 + error = dpm_suspend(PMSG_FREEZE); 344 349 if (error) 345 350 goto Recover_platform; 346 351 ··· 363 358 if (error || !in_suspend) 364 359 swsusp_free(); 365 360 366 - dpm_resume_end(in_suspend ? 367 - (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 361 + msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; 362 + dpm_resume(msg); 368 363 369 364 if (error || !in_suspend) 370 365 pm_restore_gfp_mask(); 371 366 372 367 resume_console(); 368 + 369 + Complete_devices: 370 + dpm_complete(msg); 371 + 373 372 Close: 374 373 platform_end(platform_mode); 375 374 return error;