PM: Wrap documentation to fit in 80 columns
Wrap to 80 columns. No textual change except to correct some "it's" that should be "its". Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
af42d3466b
commit
1992b66d2f
|
@ -39,9 +39,10 @@ c) Compile the driver directly into the kernel and try the test modes of
|
||||||
d) Attempt to hibernate with the driver compiled directly into the kernel
|
d) Attempt to hibernate with the driver compiled directly into the kernel
|
||||||
in the "reboot", "shutdown" and "platform" modes.
|
in the "reboot", "shutdown" and "platform" modes.
|
||||||
|
|
||||||
e) Try the test modes of suspend (see: Documentation/power/basic-pm-debugging.rst,
|
e) Try the test modes of suspend (see:
|
||||||
2). [As far as the STR tests are concerned, it should not matter whether or
|
Documentation/power/basic-pm-debugging.rst, 2). [As far as the STR tests are
|
||||||
not the driver is built as a module.]
|
concerned, it should not matter whether or not the driver is built as a
|
||||||
|
module.]
|
||||||
|
|
||||||
f) Attempt to suspend to RAM using the s2ram tool with the driver loaded
|
f) Attempt to suspend to RAM using the s2ram tool with the driver loaded
|
||||||
(see: Documentation/power/basic-pm-debugging.rst, 2).
|
(see: Documentation/power/basic-pm-debugging.rst, 2).
|
||||||
|
|
|
@ -215,30 +215,31 @@ VI. Are there any precautions to be taken to prevent freezing failures?
|
||||||
|
|
||||||
Yes, there are.
|
Yes, there are.
|
||||||
|
|
||||||
First of all, grabbing the 'system_transition_mutex' lock to mutually exclude a piece of code
|
First of all, grabbing the 'system_transition_mutex' lock to mutually exclude a
|
||||||
from system-wide sleep such as suspend/hibernation is not encouraged.
|
piece of code from system-wide sleep such as suspend/hibernation is not
|
||||||
If possible, that piece of code must instead hook onto the suspend/hibernation
|
encouraged. If possible, that piece of code must instead hook onto the
|
||||||
notifiers to achieve mutual exclusion. Look at the CPU-Hotplug code
|
suspend/hibernation notifiers to achieve mutual exclusion. Look at the
|
||||||
(kernel/cpu.c) for an example.
|
CPU-Hotplug code (kernel/cpu.c) for an example.
|
||||||
|
|
||||||
However, if that is not feasible, and grabbing 'system_transition_mutex' is deemed necessary,
|
However, if that is not feasible, and grabbing 'system_transition_mutex' is
|
||||||
it is strongly discouraged to directly call mutex_[un]lock(&system_transition_mutex) since
|
deemed necessary, it is strongly discouraged to directly call
|
||||||
that could lead to freezing failures, because if the suspend/hibernate code
|
mutex_[un]lock(&system_transition_mutex) since that could lead to freezing
|
||||||
successfully acquired the 'system_transition_mutex' lock, and hence that other entity failed
|
failures, because if the suspend/hibernate code successfully acquired the
|
||||||
to acquire the lock, then that task would get blocked in TASK_UNINTERRUPTIBLE
|
'system_transition_mutex' lock, and hence that other entity failed to acquire
|
||||||
state. As a consequence, the freezer would not be able to freeze that task,
|
the lock, then that task would get blocked in TASK_UNINTERRUPTIBLE state. As a
|
||||||
leading to freezing failure.
|
consequence, the freezer would not be able to freeze that task, leading to
|
||||||
|
freezing failure.
|
||||||
|
|
||||||
However, the [un]lock_system_sleep() APIs are safe to use in this scenario,
|
However, the [un]lock_system_sleep() APIs are safe to use in this scenario,
|
||||||
since they ask the freezer to skip freezing this task, since it is anyway
|
since they ask the freezer to skip freezing this task, since it is anyway
|
||||||
"frozen enough" as it is blocked on 'system_transition_mutex', which will be released
|
"frozen enough" as it is blocked on 'system_transition_mutex', which will be
|
||||||
only after the entire suspend/hibernation sequence is complete.
|
released only after the entire suspend/hibernation sequence is complete. So, to
|
||||||
So, to summarize, use [un]lock_system_sleep() instead of directly using
|
summarize, use [un]lock_system_sleep() instead of directly using
|
||||||
mutex_[un]lock(&system_transition_mutex). That would prevent freezing failures.
|
mutex_[un]lock(&system_transition_mutex). That would prevent freezing failures.
|
||||||
|
|
||||||
V. Miscellaneous
|
V. Miscellaneous
|
||||||
================
|
================
|
||||||
|
|
||||||
/sys/power/pm_freeze_timeout controls how long it will cost at most to freeze
|
/sys/power/pm_freeze_timeout controls how long it will cost at most to freeze
|
||||||
all user space processes or all freezable kernel threads, in unit of millisecond.
|
all user space processes or all freezable kernel threads, in unit of
|
||||||
The default value is 20000, with range of unsigned integer.
|
millisecond. The default value is 20000, with range of unsigned integer.
|
||||||
|
|
|
@ -73,19 +73,21 @@ factors. Example usage: Thermal management or other exceptional situations where
|
||||||
SoC framework might choose to disable a higher frequency OPP to safely continue
|
SoC framework might choose to disable a higher frequency OPP to safely continue
|
||||||
operations until that OPP could be re-enabled if possible.
|
operations until that OPP could be re-enabled if possible.
|
||||||
|
|
||||||
OPP library facilitates this concept in it's implementation. The following
|
OPP library facilitates this concept in its implementation. The following
|
||||||
operational functions operate only on available opps:
|
operational functions operate only on available opps:
|
||||||
opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count
|
opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq,
|
||||||
|
dev_pm_opp_get_opp_count
|
||||||
|
|
||||||
dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then
|
dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer
|
||||||
be used for dev_pm_opp_enable/disable functions to make an opp available as required.
|
which can then be used for dev_pm_opp_enable/disable functions to make an
|
||||||
|
opp available as required.
|
||||||
|
|
||||||
WARNING: Users of OPP library should refresh their availability count using
|
WARNING: Users of OPP library should refresh their availability count using
|
||||||
get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the
|
get_opp_count if dev_pm_opp_enable/disable functions are invoked for a
|
||||||
exact mechanism to trigger these or the notification mechanism to other
|
device, the exact mechanism to trigger these or the notification mechanism
|
||||||
dependent subsystems such as cpufreq are left to the discretion of the SoC
|
to other dependent subsystems such as cpufreq are left to the discretion of
|
||||||
specific framework which uses the OPP library. Similar care needs to be taken
|
the SoC specific framework which uses the OPP library. Similar care needs
|
||||||
care to refresh the cpufreq table in cases of these operations.
|
to be taken care to refresh the cpufreq table in cases of these operations.
|
||||||
|
|
||||||
2. Initial OPP List Registration
|
2. Initial OPP List Registration
|
||||||
================================
|
================================
|
||||||
|
@ -99,11 +101,11 @@ OPPs dynamically using the dev_pm_opp_enable / disable functions.
|
||||||
dev_pm_opp_add
|
dev_pm_opp_add
|
||||||
Add a new OPP for a specific domain represented by the device pointer.
|
Add a new OPP for a specific domain represented by the device pointer.
|
||||||
The OPP is defined using the frequency and voltage. Once added, the OPP
|
The OPP is defined using the frequency and voltage. Once added, the OPP
|
||||||
is assumed to be available and control of it's availability can be done
|
is assumed to be available and control of its availability can be done
|
||||||
with the dev_pm_opp_enable/disable functions. OPP library internally stores
|
with the dev_pm_opp_enable/disable functions. OPP library
|
||||||
and manages this information in the opp struct. This function may be
|
internally stores and manages this information in the opp struct.
|
||||||
used by SoC framework to define a optimal list as per the demands of
|
This function may be used by SoC framework to define a optimal list
|
||||||
SoC usage environment.
|
as per the demands of SoC usage environment.
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
Do not use this function in interrupt context.
|
Do not use this function in interrupt context.
|
||||||
|
@ -354,7 +356,7 @@ struct dev_pm_opp
|
||||||
|
|
||||||
struct device
|
struct device
|
||||||
This is used to identify a domain to the OPP layer. The
|
This is used to identify a domain to the OPP layer. The
|
||||||
nature of the device and it's implementation is left to the user of
|
nature of the device and its implementation is left to the user of
|
||||||
OPP library such as the SoC framework.
|
OPP library such as the SoC framework.
|
||||||
|
|
||||||
Overall, in a simplistic view, the data structure operations is represented as
|
Overall, in a simplistic view, the data structure operations is represented as
|
||||||
|
|
|
@ -426,12 +426,12 @@ pm->runtime_idle() callback.
|
||||||
2.4. System-Wide Power Transitions
|
2.4. System-Wide Power Transitions
|
||||||
----------------------------------
|
----------------------------------
|
||||||
There are a few different types of system-wide power transitions, described in
|
There are a few different types of system-wide power transitions, described in
|
||||||
Documentation/driver-api/pm/devices.rst. Each of them requires devices to be handled
|
Documentation/driver-api/pm/devices.rst. Each of them requires devices to be
|
||||||
in a specific way and the PM core executes subsystem-level power management
|
handled in a specific way and the PM core executes subsystem-level power
|
||||||
callbacks for this purpose. They are executed in phases such that each phase
|
management callbacks for this purpose. They are executed in phases such that
|
||||||
involves executing the same subsystem-level callback for every device belonging
|
each phase involves executing the same subsystem-level callback for every device
|
||||||
to the given subsystem before the next phase begins. These phases always run
|
belonging to the given subsystem before the next phase begins. These phases
|
||||||
after tasks have been frozen.
|
always run after tasks have been frozen.
|
||||||
|
|
||||||
2.4.1. System Suspend
|
2.4.1. System Suspend
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -636,12 +636,12 @@ System restore requires a hibernation image to be loaded into memory and the
|
||||||
pre-hibernation memory contents to be restored before the pre-hibernation system
|
pre-hibernation memory contents to be restored before the pre-hibernation system
|
||||||
activity can be resumed.
|
activity can be resumed.
|
||||||
|
|
||||||
As described in Documentation/driver-api/pm/devices.rst, the hibernation image is loaded
|
As described in Documentation/driver-api/pm/devices.rst, the hibernation image
|
||||||
into memory by a fresh instance of the kernel, called the boot kernel, which in
|
is loaded into memory by a fresh instance of the kernel, called the boot kernel,
|
||||||
turn is loaded and run by a boot loader in the usual way. After the boot kernel
|
which in turn is loaded and run by a boot loader in the usual way. After the
|
||||||
has loaded the image, it needs to replace its own code and data with the code
|
boot kernel has loaded the image, it needs to replace its own code and data with
|
||||||
and data of the "hibernated" kernel stored within the image, called the image
|
the code and data of the "hibernated" kernel stored within the image, called the
|
||||||
kernel. For this purpose all devices are frozen just like before creating
|
image kernel. For this purpose all devices are frozen just like before creating
|
||||||
the image during hibernation, in the
|
the image during hibernation, in the
|
||||||
|
|
||||||
prepare, freeze, freeze_noirq
|
prepare, freeze, freeze_noirq
|
||||||
|
@ -691,8 +691,8 @@ controlling the runtime power management of their devices.
|
||||||
|
|
||||||
At the time of this writing there are two ways to define power management
|
At the time of this writing there are two ways to define power management
|
||||||
callbacks for a PCI device driver, the recommended one, based on using a
|
callbacks for a PCI device driver, the recommended one, based on using a
|
||||||
dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and the
|
dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and
|
||||||
"legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and
|
the "legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and
|
||||||
.resume() callbacks from struct pci_driver are used. The legacy approach,
|
.resume() callbacks from struct pci_driver are used. The legacy approach,
|
||||||
however, doesn't allow one to define runtime power management callbacks and is
|
however, doesn't allow one to define runtime power management callbacks and is
|
||||||
not really suitable for any new drivers. Therefore it is not covered by this
|
not really suitable for any new drivers. Therefore it is not covered by this
|
||||||
|
|
|
@ -8,8 +8,8 @@ one of the parameters.
|
||||||
|
|
||||||
Two different PM QoS frameworks are available:
|
Two different PM QoS frameworks are available:
|
||||||
1. PM QoS classes for cpu_dma_latency
|
1. PM QoS classes for cpu_dma_latency
|
||||||
2. the per-device PM QoS framework provides the API to manage the per-device latency
|
2. The per-device PM QoS framework provides the API to manage the
|
||||||
constraints and PM QoS flags.
|
per-device latency constraints and PM QoS flags.
|
||||||
|
|
||||||
Each parameters have defined units:
|
Each parameters have defined units:
|
||||||
|
|
||||||
|
@ -47,14 +47,14 @@ void pm_qos_add_request(handle, param_class, target_value):
|
||||||
pm_qos API functions.
|
pm_qos API functions.
|
||||||
|
|
||||||
void pm_qos_update_request(handle, new_target_value):
|
void pm_qos_update_request(handle, new_target_value):
|
||||||
Will update the list element pointed to by the handle with the new target value
|
Will update the list element pointed to by the handle with the new target
|
||||||
and recompute the new aggregated target, calling the notification tree if the
|
value and recompute the new aggregated target, calling the notification tree
|
||||||
target is changed.
|
if the target is changed.
|
||||||
|
|
||||||
void pm_qos_remove_request(handle):
|
void pm_qos_remove_request(handle):
|
||||||
Will remove the element. After removal it will update the aggregate target and
|
Will remove the element. After removal it will update the aggregate target
|
||||||
call the notification tree if the target was changed as a result of removing
|
and call the notification tree if the target was changed as a result of
|
||||||
the request.
|
removing the request.
|
||||||
|
|
||||||
int pm_qos_request(param_class):
|
int pm_qos_request(param_class):
|
||||||
Returns the aggregated value for a given PM QoS class.
|
Returns the aggregated value for a given PM QoS class.
|
||||||
|
@ -167,9 +167,9 @@ int dev_pm_qos_expose_flags(device, value)
|
||||||
change the value of the PM_QOS_FLAG_NO_POWER_OFF flag.
|
change the value of the PM_QOS_FLAG_NO_POWER_OFF flag.
|
||||||
|
|
||||||
void dev_pm_qos_hide_flags(device)
|
void dev_pm_qos_hide_flags(device)
|
||||||
Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS list
|
Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS
|
||||||
of flags and remove sysfs attribute pm_qos_no_power_off from the device's power
|
list of flags and remove sysfs attribute pm_qos_no_power_off from the device's
|
||||||
directory.
|
power directory.
|
||||||
|
|
||||||
Notification mechanisms:
|
Notification mechanisms:
|
||||||
|
|
||||||
|
@ -179,8 +179,8 @@ int dev_pm_qos_add_notifier(device, notifier, type):
|
||||||
Adds a notification callback function for the device for a particular request
|
Adds a notification callback function for the device for a particular request
|
||||||
type.
|
type.
|
||||||
|
|
||||||
The callback is called when the aggregated value of the device constraints list
|
The callback is called when the aggregated value of the device constraints
|
||||||
is changed.
|
list is changed.
|
||||||
|
|
||||||
int dev_pm_qos_remove_notifier(device, notifier, type):
|
int dev_pm_qos_remove_notifier(device, notifier, type):
|
||||||
Removes the notification callback function for the device.
|
Removes the notification callback function for the device.
|
||||||
|
|
|
@ -268,8 +268,8 @@ defined in include/linux/pm.h:
|
||||||
`unsigned int runtime_auto;`
|
`unsigned int runtime_auto;`
|
||||||
- if set, indicates that the user space has allowed the device driver to
|
- if set, indicates that the user space has allowed the device driver to
|
||||||
power manage the device at run time via the /sys/devices/.../power/control
|
power manage the device at run time via the /sys/devices/.../power/control
|
||||||
`interface;` it may only be modified with the help of the pm_runtime_allow()
|
`interface;` it may only be modified with the help of the
|
||||||
and pm_runtime_forbid() helper functions
|
pm_runtime_allow() and pm_runtime_forbid() helper functions
|
||||||
|
|
||||||
`unsigned int no_callbacks;`
|
`unsigned int no_callbacks;`
|
||||||
- indicates that the device does not use the runtime PM callbacks (see
|
- indicates that the device does not use the runtime PM callbacks (see
|
||||||
|
|
|
@ -106,8 +106,8 @@ execution during resume):
|
||||||
* Release system_transition_mutex lock.
|
* Release system_transition_mutex lock.
|
||||||
|
|
||||||
|
|
||||||
It is to be noted here that the system_transition_mutex lock is acquired at the very
|
It is to be noted here that the system_transition_mutex lock is acquired at the
|
||||||
beginning, when we are just starting out to suspend, and then released only
|
very beginning, when we are just starting out to suspend, and then released only
|
||||||
after the entire cycle is complete (i.e., suspend + resume).
|
after the entire cycle is complete (i.e., suspend + resume).
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -165,7 +165,8 @@ Important files and functions/entry points:
|
||||||
|
|
||||||
- kernel/power/process.c : freeze_processes(), thaw_processes()
|
- kernel/power/process.c : freeze_processes(), thaw_processes()
|
||||||
- kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish()
|
- kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish()
|
||||||
- kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](), [disable|enable]_nonboot_cpus()
|
- kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](),
|
||||||
|
[disable|enable]_nonboot_cpus()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,8 @@ In a really perfect world::
|
||||||
|
|
||||||
echo 1 > /proc/acpi/sleep # for standby
|
echo 1 > /proc/acpi/sleep # for standby
|
||||||
echo 2 > /proc/acpi/sleep # for suspend to ram
|
echo 2 > /proc/acpi/sleep # for suspend to ram
|
||||||
echo 3 > /proc/acpi/sleep # for suspend to ram, but with more power conservative
|
echo 3 > /proc/acpi/sleep # for suspend to ram, but with more power
|
||||||
|
# conservative
|
||||||
echo 4 > /proc/acpi/sleep # for suspend to disk
|
echo 4 > /proc/acpi/sleep # for suspend to disk
|
||||||
echo 5 > /proc/acpi/sleep # for shutdown unfriendly the system
|
echo 5 > /proc/acpi/sleep # for shutdown unfriendly the system
|
||||||
|
|
||||||
|
@ -192,8 +193,8 @@ Q:
|
||||||
|
|
||||||
A:
|
A:
|
||||||
The freezing of tasks is a mechanism by which user space processes and some
|
The freezing of tasks is a mechanism by which user space processes and some
|
||||||
kernel threads are controlled during hibernation or system-wide suspend (on some
|
kernel threads are controlled during hibernation or system-wide suspend (on
|
||||||
architectures). See freezing-of-tasks.txt for details.
|
some architectures). See freezing-of-tasks.txt for details.
|
||||||
|
|
||||||
Q:
|
Q:
|
||||||
What is the difference between "platform" and "shutdown"?
|
What is the difference between "platform" and "shutdown"?
|
||||||
|
@ -282,7 +283,8 @@ A:
|
||||||
suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
|
suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
|
||||||
with state snapshot
|
with state snapshot
|
||||||
|
|
||||||
state snapshot: copy of whole used memory is taken with interrupts disabled
|
state snapshot: copy of whole used memory is taken with interrupts
|
||||||
|
disabled
|
||||||
|
|
||||||
resume(): devices are woken up so that we can write image to swap
|
resume(): devices are woken up so that we can write image to swap
|
||||||
|
|
||||||
|
@ -353,8 +355,8 @@ Q:
|
||||||
|
|
||||||
A:
|
A:
|
||||||
Generally, yes, you can. However, it requires you to use the "resume=" and
|
Generally, yes, you can. However, it requires you to use the "resume=" and
|
||||||
"resume_offset=" kernel command line parameters, so the resume from a swap file
|
"resume_offset=" kernel command line parameters, so the resume from a swap
|
||||||
cannot be initiated from an initrd or initramfs image. See
|
file cannot be initiated from an initrd or initramfs image. See
|
||||||
swsusp-and-swap-files.txt for details.
|
swsusp-and-swap-files.txt for details.
|
||||||
|
|
||||||
Q:
|
Q:
|
||||||
|
|
Loading…
Reference in New Issue