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>
This commit is contained in:
Rafael J. Wysocki
2011-05-17 23:26:00 +02:00
parent c650da23d5
commit 91e7c75ba9
5 changed files with 59 additions and 41 deletions
+21 -26
View File
@@ -1,46 +1,41 @@
Suspend notifiers
(C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
(C) 2007-2011 Rafael J. Wysocki <rjw@sisk.pl>, GPL
There are some operations that device drivers may want to carry out in their
.suspend() routines, but shouldn't, because they can cause the hibernation or
suspend to fail. For example, a driver may want to allocate a substantial amount
of memory (like 50 MB) in .suspend(), but that shouldn't be done after the
swsusp's memory shrinker has run.
There are some operations that subsystems or drivers may want to carry out
before hibernation/suspend or after restore/resume, but they require the system
to be fully functional, so the drivers' and subsystems' .suspend() and .resume()
or even .prepare() and .complete() callbacks are not suitable for this purpose.
For example, device drivers may want to upload firmware to their devices after
resume/restore, but they cannot do it by calling request_firmware() from their
.resume() or .complete() routines (user land processes are frozen at these
points). The solution may be to load the firmware into memory before processes
are frozen and upload it from there in the .resume() routine.
A suspend/hibernation notifier may be used for this purpose.
Also, there may be some operations, that subsystems want to carry out before a
hibernation/suspend or after a restore/resume, requiring the system to be fully
functional, so the drivers' .suspend() and .resume() routines are not suitable
for this purpose. For example, device drivers may want to upload firmware to
their devices after a restore from a hibernation image, but they cannot do it by
calling request_firmware() from their .resume() routines (user land processes
are frozen at this point). The solution may be to load the firmware into
memory before processes are frozen and upload it from there in the .resume()
routine. Of course, a hibernation notifier may be used for this purpose.
The subsystems that have such needs can register suspend notifiers that will be
called upon the following events by the suspend core:
The subsystems or drivers having such needs can register suspend notifiers that
will be called upon the following events by the PM core:
PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will
be frozen immediately.
PM_POST_HIBERNATION The system memory state has been restored from a
hibernation image or an error occurred during the
hibernation. Device drivers' .resume() callbacks have
hibernation image or an error occurred during
hibernation. Device drivers' restore callbacks have
been executed and tasks have been thawed.
PM_RESTORE_PREPARE The system is going to restore a hibernation image.
If all goes well the restored kernel will issue a
If all goes well, the restored kernel will issue a
PM_POST_HIBERNATION notification.
PM_POST_RESTORE An error occurred during the hibernation restore.
Device drivers' .resume() callbacks have been executed
PM_POST_RESTORE An error occurred during restore from hibernation.
Device drivers' restore callbacks have been executed
and tasks have been thawed.
PM_SUSPEND_PREPARE The system is preparing for a suspend.
PM_SUSPEND_PREPARE The system is preparing for suspend.
PM_POST_SUSPEND The system has just resumed or an error occurred during
the suspend. Device drivers' .resume() callbacks have
been executed and tasks have been thawed.
suspend. Device drivers' resume callbacks have been
executed and tasks have been thawed.
It is generally assumed that whatever the notifiers do for
PM_HIBERNATION_PREPARE, should be undone for PM_POST_HIBERNATION. Analogously,