Documentation: PM: sleep: Update driver flags documentation

Update the documentation of the driver flags for system-wide power
management to reflect the current code flows and be more consistent.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Rafael J. Wysocki 2020-04-18 18:55:32 +02:00
parent 2a3f34750b
commit 2fff3f73e8
3 changed files with 115 additions and 83 deletions

View File

@ -772,62 +772,107 @@ the state of devices (possibly except for resuming them from runtime suspend)
from their ``->prepare`` and ``->suspend`` callbacks (or equivalent) *before* from their ``->prepare`` and ``->suspend`` callbacks (or equivalent) *before*
invoking device drivers' ``->suspend`` callbacks (or equivalent). invoking device drivers' ``->suspend`` callbacks (or equivalent).
.. _smart_suspend_flag:
The ``DPM_FLAG_SMART_SUSPEND`` Driver Flag
------------------------------------------
Some bus types and PM domains have a policy to resume all devices from runtime Some bus types and PM domains have a policy to resume all devices from runtime
suspend upfront in their ``->suspend`` callbacks, but that may not be really suspend upfront in their ``->suspend`` callbacks, but that may not be really
necessary if the driver of the device can cope with runtime-suspended devices. necessary if the driver of the device can cope with runtime-suspended devices.
The driver can indicate that by setting ``DPM_FLAG_SMART_SUSPEND`` in The driver can indicate that by setting ``DPM_FLAG_SMART_SUSPEND`` in
:c:member:`power.driver_flags` at the probe time, by passing it to the :c:member:`power.driver_flags` at the probe time with the help of the
:c:func:`dev_pm_set_driver_flags` helper. That also may cause middle-layer code :c:func:`dev_pm_set_driver_flags` helper routine.
However, setting that flag also causes the PM core and middle-layer code
(bus types, PM domains etc.) to skip the ``->suspend_late`` and (bus types, PM domains etc.) to skip the ``->suspend_late`` and
``->suspend_noirq`` callbacks provided by the driver if the device remains in ``->suspend_noirq`` callbacks provided by the driver if the device remains in
runtime suspend at the beginning of the ``suspend_late`` phase of system-wide runtime suspend during the ``suspend_late`` phase of system-wide suspend (or
suspend (or in the ``poweroff_late`` phase of hibernation), when runtime PM during the ``poweroff_late`` or ``freeze_late`` phase of hibernation),
has been disabled for it, under the assumption that its state should not change after runtime PM was disabled for it. [Without doing that, the same driver
after that point until the system-wide transition is over (the PM core itself callback might be executed twice in a row for the same device, which would not
does that for devices whose "noirq", "late" and "early" system-wide PM callbacks be valid in general.] If the middle-layer system-wide PM callbacks are present
are executed directly by it). If that happens, the driver's system-wide resume for the device, they are responsible for doing the above, and the PM core takes
callbacks, if present, may still be invoked during the subsequent system-wide care of it otherwise.
resume transition and the device's runtime power management status may be set
to "active" before enabling runtime PM for it, so the driver must be prepared to In addition, with ``DPM_FLAG_SMART_SUSPEND`` set, the driver's ``->thaw_late``
cope with the invocation of its system-wide resume callbacks back-to-back with and ``->thaw_noirq`` callbacks are skipped if the device remained in runtime
its ``->runtime_suspend`` one (without the intervening ``->runtime_resume`` and suspend during the preceding "freeze" transition related to hibernation.
so on) and the final state of the device must reflect the "active" runtime PM Again, if the middle-layer callbacks are present for the device, they are
status in that case. responsible for doing that, or the PM core takes care of it otherwise.
The ``DPM_FLAG_MAY_SKIP_RESUME`` Driver Flag
--------------------------------------------
During system-wide resume from a sleep state it's easiest to put devices into During system-wide resume from a sleep state it's easiest to put devices into
the full-power state, as explained in :file:`Documentation/power/runtime_pm.rst`. the full-power state, as explained in :file:`Documentation/power/runtime_pm.rst`.
[Refer to that document for more information regarding this particular issue as [Refer to that document for more information regarding this particular issue as
well as for information on the device runtime power management framework in well as for information on the device runtime power management framework in
general.] general.] However, it often is desirable to leave devices in suspend after
system transitions to the working state, especially if those devices had been in
However, it often is desirable to leave devices in suspend after system
transitions to the working state, especially if those devices had been in
runtime suspend before the preceding system-wide suspend (or analogous) runtime suspend before the preceding system-wide suspend (or analogous)
transition. Device drivers can use the ``DPM_FLAG_MAY_SKIP_RESUME`` flag to transition.
indicate to the PM core (and middle-layer code) that they prefer the specific
devices handled by them to be left suspended and they have no problems with
skipping their system-wide resume callbacks for this reason. Whether or not the
devices will actually be left in suspend may depend on their state before the
given system suspend-resume cycle and on the type of the system transition under
way. In particular, devices are not left suspended if that transition is a
restore from hibernation, as device states are not guaranteed to be reflected
by the information stored in the hibernation image in that case.
The middle-layer code involved in the handling of the device is expected to To that end, device drivers can use the ``DPM_FLAG_MAY_SKIP_RESUME`` flag to
indicate to the PM core if the device may be left in suspend by setting its indicate to the PM core and middle-layer code that they allow their "noirq" and
:c:member:`power.may_skip_resume` status bit which is checked by the PM core "early" resume callbacks to be skipped if the device can be left in suspend
during the "noirq" phase of the preceding system-wide suspend (or analogous) after system-wide PM transitions to the working state. Whether or not that is
transition. The middle layer is then responsible for handling the device as the case generally depends on the state of the device before the given system
appropriate in its "noirq" resume callback, which is executed regardless of suspend-resume cycle and on the type of the system transition under way.
whether or not the device is left suspended, but the other resume callbacks In particular, the "restore" and "thaw" transitions related to hibernation are
(except for ``->complete``) will be skipped automatically by the PM core if the not affected by ``DPM_FLAG_MAY_SKIP_RESUME`` at all. [All devices are always
device really can be left in suspend. resumed during the "restore" transition and whether or not any driver callbacks
are skipped during the "freeze" transition depends whether or not the
``DPM_FLAG_SMART_SUSPEND`` flag is set (see `above <smart_suspend_flag_>`_).]
For devices whose "noirq", "late" and "early" driver callbacks are invoked The ``DPM_FLAG_MAY_SKIP_RESUME`` flag is taken into account in combination with
directly by the PM core, all of the system-wide resume callbacks are skipped if the :c:member:`power.may_skip_resume` status bit set by the PM core during the
``DPM_FLAG_MAY_SKIP_RESUME`` is set and the device is in runtime suspend during "suspend" phase of suspend-type transitions. If the driver or the middle layer
the ``suspend_noirq`` (or analogous) phase or the transition under way is a has a reason to prevent the driver's "noirq" and "early" resume callbacks from
proper system suspend (rather than anything related to hibernation) and the being skipped during the subsequent resume transition of the system, it should
device's wakeup settings are suitable for runtime PM (that is, it cannot clear :c:member:`power.may_skip_resume` in its ``->suspend``, ``->suspend_late``
generate wakeup signals at all or it is allowed to wake up the system from or ``->suspend_noirq`` callback. [Note that the drivers setting
sleep). ``DPM_FLAG_SMART_SUSPEND`` need to clear :c:member:`power.may_skip_resume` in
their ``->suspend`` callback in case the other two are skipped.]
Setting the :c:member:`power.may_skip_resume` status bit along with the
``DPM_FLAG_MAY_SKIP_RESUME`` flag is necessary, but generally not sufficient,
for the driver's "noirq" and "early" resume callbacks to be skipped. Whether or
not they should be skipped can be determined by evaluating the
:c:func:`dev_pm_skip_resume` helper function.
If that function returns ``true``, the driver's "noirq" and "early" resume
callbacks should be skipped and the device's runtime PM status will be set to
"suspended" by the PM core. Otherwise, if the device was runtime-suspended
during the preceding system-wide suspend transition and
``DPM_FLAG_SMART_SUSPEND`` is set for it, its runtime PM status will be set to
"active" by the PM core. [Hence, the drivers that do not set
``DPM_FLAG_SMART_SUSPEND`` should not expect the runtime PM status of their
devices to be changed from "suspended" to "active" by the PM core during
system-wide resume-type transitions.]
If the ``DPM_FLAG_MAY_SKIP_RESUME`` flag is not set for a device, but
``DPM_FLAG_SMART_SUSPEND`` is set and the driver's "late" and "noirq" suspend
callbacks are skipped, its system-wide "noirq" and "early" resume callbacks, if
present, are invoked as usual and the device's runtime PM status is set to
"active" by the PM core before enabling runtime PM for it. In that case, the
driver must be prepared to cope with the invocation of its system-wide resume
callbacks back-to-back with its ``->runtime_suspend`` one (without the
intervening ``->runtime_resume`` and system-wide suspend callbacks) and the
final state of the device must reflect the "active" runtime PM status in that
case. [Note that this is not a problem at all if the driver's
``->suspend_late`` callback pointer points to the same function as its
``->runtime_suspend`` one and its ``->resume_early`` callback pointer points to
the same function as the ``->runtime_resume`` one, while none of the other
system-wide suspend-resume callbacks of the driver are present, for example.]
Likewise, if ``DPM_FLAG_MAY_SKIP_RESUME`` is set for a device, its driver's
system-wide "noirq" and "early" resume callbacks may be skipped while its "late"
and "noirq" suspend callbacks may have been executed (in principle, regardless
of whether or not ``DPM_FLAG_SMART_SUSPEND`` is set). In that case, the driver
needs to be able to cope with the invocation of its ``->runtime_resume``
callback back-to-back with its "late" and "noirq" suspend ones. [For instance,
that is not a concern if the driver sets both ``DPM_FLAG_SMART_SUSPEND`` and
``DPM_FLAG_MAY_SKIP_RESUME`` and uses the same pair of suspend/resume callback
functions for runtime PM and system-wide suspend/resume.]

View File

@ -1010,32 +1010,33 @@ if the device is in runtime suspend when the system suspend starts. That also
affects all of the ancestors of the device, so this flag should only be used if affects all of the ancestors of the device, so this flag should only be used if
absolutely necessary. absolutely necessary.
The DPM_FLAG_SMART_PREPARE flag instructs the PCI bus type to only return a The DPM_FLAG_SMART_PREPARE flag causes the PCI bus type to return a positive
positive value from pci_pm_prepare() if the ->prepare callback provided by the value from pci_pm_prepare() only if the ->prepare callback provided by the
driver of the device returns a positive value. That allows the driver to opt driver of the device returns a positive value. That allows the driver to opt
out from using the direct-complete mechanism dynamically. out from using the direct-complete mechanism dynamically (whereas setting
DPM_FLAG_NO_DIRECT_COMPLETE means permanent opt-out).
The DPM_FLAG_SMART_SUSPEND flag tells the PCI bus type that from the driver's The DPM_FLAG_SMART_SUSPEND flag tells the PCI bus type that from the driver's
perspective the device can be safely left in runtime suspend during system perspective the device can be safely left in runtime suspend during system
suspend. That causes pci_pm_suspend(), pci_pm_freeze() and pci_pm_poweroff() suspend. That causes pci_pm_suspend(), pci_pm_freeze() and pci_pm_poweroff()
to skip resuming the device from runtime suspend unless there are PCI-specific to avoid resuming the device from runtime suspend unless there are PCI-specific
reasons for doing that. Also, it causes pci_pm_suspend_late/noirq(), reasons for doing that. Also, it causes pci_pm_suspend_late/noirq() and
pci_pm_freeze_late/noirq() and pci_pm_poweroff_late/noirq() to return early pci_pm_poweroff_late/noirq() to return early if the device remains in runtime
if the device remains in runtime suspend in the beginning of the "late" phase suspend during the "late" phase of the system-wide transition under way.
of the system-wide transition under way. Moreover, if the device is in Moreover, if the device is in runtime suspend in pci_pm_resume_noirq() or
runtime suspend in pci_pm_resume_noirq() or pci_pm_restore_noirq(), its runtime pci_pm_restore_noirq(), its runtime PM status will be changed to "active" (as it
power management status will be changed to "active" (as it is going to be put is going to be put into D0 going forward).
into D0 going forward), but if it is in runtime suspend in pci_pm_thaw_noirq(),
the function will set the power.direct_complete flag for it (to make the PM core
skip the subsequent "thaw" callbacks for it) and return.
Setting the DPM_FLAG_MAY_SKIP_RESUME flag means that the driver prefers the Setting the DPM_FLAG_MAY_SKIP_RESUME flag means that the driver allows its
device to be left in suspend after system-wide transitions to the working state. "noirq" and "early" resume callbacks to be skipped if the device can be left
This flag is checked by the PM core, but the PCI bus type informs the PM core in suspend after a system-wide transition into the working state. This flag is
which devices may be left in suspend from its perspective (that happens during taken into consideration by the PM core along with the power.may_skip_resume
the "noirq" phase of system-wide suspend and analogous transitions) and next it status bit of the device which is set by pci_pm_suspend_noirq() in certain
uses the dev_pm_skip_resume() helper to decide whether or not to return from situations. If the PM core determines that the driver's "noirq" and "early"
pci_pm_resume_noirq() and pci_pm_resume_early() upfront. resume callbacks should be skipped, the dev_pm_skip_resume() helper function
will return "true" and that will cause pci_pm_resume_noirq() and
pci_pm_resume_early() to return upfront without touching the device and
executing the driver callbacks.
3.2. Device Runtime Power Management 3.2. Device Runtime Power Management
------------------------------------ ------------------------------------

View File

@ -545,25 +545,11 @@ struct pm_subsys_data {
* cleared by the drivers as the driver core will take care of that. * cleared by the drivers as the driver core will take care of that.
* *
* NO_DIRECT_COMPLETE: Do not apply direct-complete optimization to the device. * NO_DIRECT_COMPLETE: Do not apply direct-complete optimization to the device.
* SMART_PREPARE: Check the return value of the driver's ->prepare callback. * SMART_PREPARE: Take the driver ->prepare callback return value into account.
* SMART_SUSPEND: No need to resume the device from runtime suspend. * SMART_SUSPEND: Avoid resuming the device from runtime suspend.
* MAY_SKIP_RESUME: Avoid resuming the device during system resume if possible. * MAY_SKIP_RESUME: Allow driver "noirq" and "early" callbacks to be skipped.
* *
* Setting SMART_PREPARE instructs bus types and PM domains which may want * See Documentation/driver-api/pm/devices.rst for details.
* system suspend/resume callbacks to be skipped for the device to return 0 from
* their ->prepare callbacks if the driver's ->prepare callback returns 0 (in
* other words, the system suspend/resume callbacks can only be skipped for the
* device if its driver doesn't object against that). This flag has no effect
* if NO_DIRECT_COMPLETE is set.
*
* Setting SMART_SUSPEND instructs bus types and PM domains which may want to
* runtime resume the device upfront during system suspend that doing so is not
* necessary from the driver's perspective. It also may cause them to skip
* invocations of the ->suspend_late and ->suspend_noirq callbacks provided by
* the driver if they decide to leave the device in runtime suspend.
*
* Setting MAY_SKIP_RESUME informs the PM core and middle-layer code that the
* driver prefers the device to be left in suspend after system resume.
*/ */
#define DPM_FLAG_NO_DIRECT_COMPLETE BIT(0) #define DPM_FLAG_NO_DIRECT_COMPLETE BIT(0)
#define DPM_FLAG_SMART_PREPARE BIT(1) #define DPM_FLAG_SMART_PREPARE BIT(1)