Runtime Power Management Framework for I/O Devices¶
2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
2010 Alan Stern <stern@rowland.harvard.edu>
2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1. Introduction¶
Support for runtime power management (runtime PM) of I/O devices is provided at the power management core (PM core) level by means of:
The power management workqueue pm_wq in which bus types and device drivers can put their PM-related work items. It is strongly recommended that pm_wq be used for queuing all work items related to runtime PM, because this allows them to be synchronized with system-wide power transitions (suspend to RAM, hibernation and resume from system sleep states). pm_wq is declared in include/linux/pm_runtime.h and defined in kernel/power/main.c.
A number of runtime PM fields in the ‘power’ member of ‘
struct device’ (which is of the type ‘struct dev_pm_info’, defined in include/linux/pm.h) that can be used for synchronizing runtime PM operations with one another.Three device runtime PM callbacks in ‘
struct dev_pm_ops’ (defined in include/linux/pm.h).A set of helper functions defined in drivers/base/power/runtime.c that can be used for carrying out runtime PM operations in such a way that the synchronization between them is taken care of by the PM core. Bus types and device drivers are encouraged to use these functions.
The runtime PM callbacks present in ‘struct dev_pm_ops’, the device runtime PM
fields of ‘struct dev_pm_info’ and the core helper functions provided for
runtime PM are described below.
2. Device Runtime PM Callbacks¶
There are three device runtime PM callbacks defined in ‘struct dev_pm_ops’:
struct dev_pm_ops {
...
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
...
};
Most device drivers only need to implement ->runtime_suspend() and
->runtime_resume(). The ->runtime_idle() callback is optional and rarely
implemented by peripheral device drivers, as the PM core automatically handles
suspension and autosuspend when ->runtime_idle() is omitted (or returns 0).
Subsystem and Driver Callbacks¶
The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
are executed by the PM core for the device’s subsystem that may be either of
the following:
PM domain of the device, if the device’s PM domain object, dev->pm_domain, is present.
Device type of the device, if both dev->type and dev->type->pm are present.
Device class of the device, if both dev->class and dev->class->pm are present.
Bus type of the device, if both dev->bus and dev->bus->pm are present.
If the subsystem chosen by applying the above rules doesn’t provide the relevant callback, the PM core will invoke the corresponding driver callback stored in dev->driver->pm directly (if present).
The PM core always checks which callback to use in the order given above, so the priority order of callbacks from high to low is: PM domain, device type, class and bus type. Moreover, the high-priority one will always take precedence over a low-priority one. The PM domain, bus type, device type and class callbacks are referred to as subsystem-level callbacks in what follows.
By default, the callbacks are always invoked in process context with interrupts
enabled. However, the pm_runtime_irq_safe() helper function can be used to tell
the PM core that it is safe to run the ->runtime_suspend(), ->runtime_resume()
and ->runtime_idle() callbacks for the given device in atomic context with
interrupts disabled. This implies that the callback routines in question must
not block or sleep, but it also means that the synchronous helper functions
listed at the end of Section 4 may be used for that device within an
interrupt handler or generally in an atomic context.
Callback Semantics¶
The subsystem-level suspend callback, if present, is _entirely_ _responsible_
for handling the suspend of the device as appropriate, which may, but need not
include executing the device driver’s own ->runtime_suspend() callback (from the
PM core’s point of view it is not necessary to implement a ->runtime_suspend()
callback in a device driver as long as the subsystem-level suspend callback
knows what to do to handle the device).
Once the subsystem-level suspend callback (or the driver suspend callback, if invoked directly) has completed successfully for the given device, the PM core regards the device as suspended, which need not mean that it has been put into a low power state. It is supposed to mean, however, that the device will not process data and will not communicate with the CPU(s) and RAM until the appropriate resume callback is executed for it. The runtime PM status of a device after successful execution of the suspend callback is ‘suspended’.
If the suspend callback returns -EBUSY or -EAGAIN, the device’s runtime PM status remains ‘active’, which means that the device _must_ be fully operational afterwards.
If the suspend callback returns an error code different from -EBUSY and -EAGAIN, the PM core regards this as a fatal error and will refuse to run the helper functions described in Section 4 for the device until its status is directly set to either ‘active’, or ‘suspended’ (the PM core provides special helper functions for this purpose).
In particular, if the driver requires remote wakeup capability (i.e. hardware
mechanism allowing the device to request a change of its power state, such as
PCI PME) for proper functioning and device_can_wakeup() returns ‘false’ for the
device, then ->runtime_suspend() should return -EBUSY. On the other hand, if
device_can_wakeup() returns ‘true’ for the device and the device is put into a
low-power state during the execution of the suspend callback, it is expected
that remote wakeup will be enabled for the device. Generally, remote wakeup
should be enabled for all input devices put into low-power states at run time.
The subsystem-level resume callback, if present, is entirely responsible for
handling the resume of the device as appropriate, which may, but need not
include executing the device driver’s own ->runtime_resume() callback (from the
PM core’s point of view it is not necessary to implement a ->runtime_resume()
callback in a device driver as long as the subsystem-level resume callback knows
what to do to handle the device).
Once the subsystem-level resume callback (or the driver resume callback, if invoked directly) has completed successfully, the PM core regards the device as fully operational, which means that the device _must_ be able to complete I/O operations as needed. The runtime PM status of the device is then ‘active’.
If the resume callback returns an error code, the PM core regards this as a fatal error and will refuse to run the helper functions described in Section 4 for the device, until its status is directly set to either ‘active’, or ‘suspended’ (by means of special helper functions provided by the PM core for this purpose).
The idle callback (a subsystem-level one, if present, or the driver one) is executed by the PM core whenever the device appears to be idle, which is indicated to the PM core by two counters, the device’s usage counter and the counter of ‘active’ children of the device.
If any of these counters is decreased using a helper function provided by the PM core and it turns out to be equal to zero, the other counter is checked. If that counter also is equal to zero, the PM core executes the idle callback with the device as its argument.
The action performed by the idle callback is totally dependent on the subsystem
(or driver) in question, but the expected and recommended action is to check
if the device can be suspended (i.e. if all of the conditions necessary for
suspending the device are satisfied) and to queue up a suspend request for the
device in that case. If there is no idle callback, or if the callback returns
0, then the PM core will attempt to carry out a runtime suspend of the device,
also respecting devices configured for autosuspend. In essence this means a
call to pm_runtime_autosuspend().
To prevent this suspension (for example, if the callback routine has scheduled
a delayed suspend or determined the device cannot be idle), the routine must
return a non-zero value (typically -EBUSY or -EAGAIN). Unlike
->runtime_suspend() and ->runtime_resume(), the PM core does not treat negative
return codes from ->runtime_idle() as a fatal device error; any non-zero value
simply stops the PM core from suspending the device.
Core Guarantees and Synchronization Rules¶
The helper functions provided by the PM core, described in Section 4, guarantee that the following constraints are met with respect to runtime PM callbacks for one device:
The callbacks are mutually exclusive (e.g. it is forbidden to execute ->
runtime_suspend()in parallel with ->runtime_resume()or with another instance of ->runtime_suspend()for the same device) with the exception that ->runtime_suspend()or ->runtime_resume()can be executed in parallel with ->runtime_idle()(although ->runtime_idle()will not be started while any of the other callbacks is being executed for the same device).->
runtime_idle()and ->runtime_suspend()can only be executed for ‘active’ devices (i.e. the PM core will only execute ->runtime_idle()or ->runtime_suspend()for the devices the runtime PM status of which is ‘active’).->
runtime_idle()and ->runtime_suspend()can only be executed for a device the usage counter of which is equal to zero _and_ either the counter of ‘active’ children of which is equal to zero, or the ‘power.ignore_children’ flag of which is set.->
runtime_resume()can only be executed for ‘suspended’ devices (i.e. the PM core will only execute ->runtime_resume()for the devices the runtime PM status of which is ‘suspended’).
Additionally, the helper functions provided by the PM core obey the following rules:
If ->
runtime_suspend()is about to be executed or there’s a pending request to execute it, ->runtime_idle()will not be executed for the same device.A request to execute or to schedule the execution of ->
runtime_suspend()will cancel any pending requests to execute ->runtime_idle()for the same device.If ->
runtime_resume()is about to be executed or there’s a pending request to execute it, the other callbacks will not be executed for the same device.A request to execute ->
runtime_resume()will cancel any pending or scheduled requests to execute the other callbacks for the same device, except for scheduled autosuspends.
3. Runtime PM Device Fields¶
Device PM fields are found in ‘struct dev_pm_info’, as defined in
include/linux/pm.h. Many of those fields track runtime PM configuration and
state.
-
struct dev_pm_info¶
Device power management information.
Definition:
struct dev_pm_info {
pm_message_t power_state;
bool can_wakeup:1;
bool async_suspend:1;
bool in_dpm_list:1;
bool is_prepared:1;
bool is_suspended:1;
bool is_noirq_suspended:1;
bool is_late_suspended:1;
bool no_pm:1;
bool early_init:1;
bool direct_complete:1;
u32 driver_flags;
spinlock_t lock;
#ifdef CONFIG_PM_SLEEP;
struct list_head entry;
struct completion completion;
struct wakeup_source *wakeup;
bool work_in_progress;
bool wakeup_path:1;
bool syscore:1;
bool no_pm_callbacks:1;
bool smart_suspend:1;
bool must_resume:1;
bool may_skip_resume:1;
bool out_band_wakeup:1;
bool strict_midlayer:1;
#else;
bool should_wakeup:1;
#endif;
#ifdef CONFIG_PM;
struct hrtimer suspend_timer;
u64 timer_expires;
struct work_struct work;
wait_queue_head_t wait_queue;
struct wake_irq *wakeirq;
atomic_t usage_count;
atomic_t child_count;
unsigned int disable_depth:3;
bool idle_notification:1;
bool request_pending:1;
bool deferred_resume:1;
bool needs_force_resume:1;
bool runtime_auto:1;
bool ignore_children:1;
bool no_callbacks:1;
bool irq_safe:1;
bool use_autosuspend:1;
bool timer_autosuspends:1;
bool memalloc_noio:1;
unsigned int links_count;
enum rpm_request request;
enum rpm_status runtime_status;
enum rpm_status last_status;
int runtime_error;
int autosuspend_delay;
u64 last_busy;
u64 active_time;
u64 suspended_time;
u64 accounting_timestamp;
#endif;
struct pm_subsys_data *subsys_data;
void (*set_latency_tolerance)(struct device *, s32);
struct dev_pm_qos *qos;
bool detach_power_off:1;
};
Members
power_stateLegacy power state (mostly unused in modern kernels).
can_wakeupDevice is capable of generating wakeup signals.
async_suspendDevice can be suspended and resumed asynchronously.
in_dpm_listDevice is on the dpm_list.
is_preparedDevice’s ->
prepare()callback has run successfully.is_suspendedDevice is suspended during a system sleep transition.
is_noirq_suspendedDevice’s noirq suspend callback has run successfully.
is_late_suspendedDevice’s late suspend callback has run successfully.
no_pmDevice does not participate in power management transitions.
early_initDevice was initialized before standard PM initialization.
direct_completeDevice can skip suspend/resume callbacks and remain runtime-suspended during system sleep.
driver_flagsDriver flags (e.g.
DPM_FLAG_SMART_SUSPEND) set at probe time.lockSpinlock used for synchronizing PM state transitions and runtime PM operations.
entryList head for device power management lists.
completionCompletion for synchronization during asynchronous system suspend/resume.
wakeupWakeup source object associated with the device.
work_in_progressAsynchronous PM operation in progress.
wakeup_pathDevice is in the wakeup path or can wake the system up.
syscoreDevice participates in syscore power management operations.
no_pm_callbacksDevice has no PM callbacks; handled by parent or subsystem.
smart_suspendDriver requested smart-suspend behavior.
must_resumeDevice must be resumed during system resume.
may_skip_resumeSet by subsystems to indicate driver resume callbacks may be skipped.
out_band_wakeupOut-of-band wakeup is supported.
strict_midlayerMiddle layer code does not want callbacks invoked via
pm_runtime_force_suspend()/pm_runtime_force_resume().should_wakeupWakeup flag when system sleep is not enabled.
suspend_timerHigh-resolution timer used for scheduling delayed runtime suspend and autosuspend requests.
timer_expiresTimer expiration time in nanoseconds monotonic time (runtime PM).
workWork structure used for queuing up requests into pm_wq (runtime PM).
wait_queueWait queue used if any helper functions need to wait for another state change to complete (runtime PM).
wakeirqDedicated wakeup interrupt for the device.
usage_countDevice runtime PM usage counter.
child_countCount of active children of the device (runtime PM).
disable_depthDisable counter for runtime PM (runtime PM is enabled when this is 0; initial value is 1).
idle_notificationSet if ->
runtime_idle()is being executed.request_pendingSet if a work item is queued into pm_wq (runtime PM).
deferred_resumeSet if ->
runtime_resume()should run as soon as ->runtime_suspend()completes.needs_force_resumeIndicates the device was forced into suspend by
pm_runtime_force_suspend()and must be resumed bypm_runtime_force_resume().runtime_autoUser space has allowed the driver to power manage the device at runtime via sysfs control attribute; also can be set by
pm_runtime_allow()orpm_runtime_forbid().ignore_childrenIf set, the value of child_count is ignored for runtime suspend and idle decisions.
no_callbacksIndicates the device does not use runtime PM callbacks.
irq_safeIndicates runtime PM callbacks will be invoked with the spinlock held and interrupts disabled.
use_autosuspendIndicates the device driver supports delayed runtime autosuspend.
timer_autosuspendsIndicates the runtime PM core should attempt an autosuspend rather than a normal suspend when the timer expires.
memalloc_noioIndicates memory allocation during runtime PM transitions must avoid I/O (GFP_NOIO).
links_countNumber of device links that require runtime PM coordination.
requestType of pending runtime PM request (valid if request_pending is set).
runtime_statusRuntime PM status of the device.
last_statusLast status captured before disabling runtime PM, or
RPM_BLOCKED/RPM_INVALID.runtime_errorFatal error code returned by a failing callback, blocking helpers until cleared.
autosuspend_delayDelay time in milliseconds to be used for runtime autosuspend.
last_busyTimestamp in nanoseconds when
pm_runtime_mark_last_busy()was last called. Used in calculating inactivity periods for autosuspend.active_timeAccumulated time in nanoseconds spent in
RPM_ACTIVEstate.suspended_timeAccumulated time in nanoseconds spent in
RPM_SUSPENDEDstate.accounting_timestampTimestamp in nanoseconds of the last runtime PM state accounting update.
subsys_dataSubsystem-specific power management data.
set_latency_toleranceCallback for setting latency tolerance.
qosPer-device PM Quality of Service (QoS) constraints.
detach_power_offIndicates device should be detached from PM domain on power off.
Description
Device power management information stored in the “power” member of struct
device.
4. Runtime PM Device Helper Functions¶
The following runtime PM helper functions are defined in drivers/base/power/runtime.c and include/linux/pm_runtime.h:
-
u64 pm_runtime_autosuspend_expiration(struct device *dev)¶
Get a device’s autosuspend-delay expiration time.
Parameters
struct device *devDevice to handle.
Description
Compute the autosuspend-delay expiration time based on the device’s power.last_busy time. If the delay has already expired or is disabled (negative) or the power.use_autosuspend flag isn’t set, return 0. Otherwise return the expiration time in nanoseconds.
This function may be called either with or without dev->power.lock held. Either way it can be racy, since power.last_busy may be updated at any time.
-
void pm_runtime_set_memalloc_noio(struct device *dev, bool enable)¶
Set a device’s memalloc_noio flag.
Parameters
struct device *devDevice to handle.
bool enableTrue for setting the flag and False for clearing the flag.
Description
Set the flag for all devices in the path from the device to the root device in the device tree if enable is true, otherwise clear the flag for devices in the path whose siblings don’t set the flag.
The function should only be called by block device, or network device driver for solving the deadlock problem during runtime resume/suspend:
If memory allocation with GFP_KERNEL is called inside runtime resume/suspend callback of any one of its ancestors(or the block device itself), the deadlock may be triggered inside the memory allocation since it might not complete until the block device becomes active and the involved page I/O finishes. The situation is pointed out first by Alan Stern. Network device are involved in iSCSI kind of situation.
The lock of dev_hotplug_mutex is held in the function for handling
hotplug race because pm_runtime_set_memalloc_noio() may be called
in async probe().
The function should be called between device_add() and device_del()
on the affected device(block/network device).
-
int pm_schedule_suspend(struct device *dev, unsigned int delay)¶
Set up a timer to submit a suspend request in future.
Parameters
struct device *devDevice to suspend.
unsigned int delayTime to wait before submitting a suspend request, in milliseconds.
Return
1: Success; dev is alreadyRPM_SUSPENDED.0: Success.Error code on failure.
-
int __pm_runtime_idle(struct device *dev, int rpmflags)¶
Core entry point for runtime idle operations.
Parameters
struct device *devDevice to send idle notification for.
int rpmflagsFlag bits.
Description
Carry out an idle check for dev, either synchronous or asynchronous.
If RPM_GET_PUT is set in rpmflags, decrement the device’s usage count
first, proceeding with idle notification only if the counter drops to zero.
This routine may be called in atomic context if the RPM_ASYNC flag is set,
or if pm_runtime_irq_safe() has been called.
-
int __pm_runtime_suspend(struct device *dev, int rpmflags)¶
Core entry point for runtime put/suspend operations.
Parameters
struct device *devDevice to suspend.
int rpmflagsFlag bits.
Description
Carry out a suspend operation for dev, either synchronous or asynchronous.
If RPM_GET_PUT is set in rpmflags, decrement the device’s usage count
first, proceeding with suspend only if the counter drops to zero.
This routine may be called in atomic context if the RPM_ASYNC flag is set,
or if pm_runtime_irq_safe() has been called.
-
int __pm_runtime_resume(struct device *dev, int rpmflags)¶
Core entry point for runtime resume operations.
Parameters
struct device *devDevice to resume.
int rpmflagsFlag bits.
Description
Carry out a runtime resume operation for dev, either synchronous or
asynchronous. If RPM_GET_PUT is set in rpmflags, increment the device’s
usage count first, then bring the device to RPM_ACTIVE state.
This routine may be called in atomic context if the RPM_ASYNC flag is set,
or if pm_runtime_irq_safe() has been called.
Parameters
struct device *devTarget device.
Description
Increment the runtime PM usage counter of dev if its runtime PM status is
already RPM_ACTIVE.
Return
-EINVAL: Runtime PM is disabled for dev. The usage counter is not incremented.1: Success; usage counter is incremented.0: dev was not active.
Parameters
struct device *devTarget device.
Description
Increment the runtime PM usage counter of dev if it is “in use.” A device
is considered in use if its runtime PM status is RPM_ACTIVE and its runtime
PM usage counter is greater than 0, or if it is not ignoring children and
its active child count is nonzero.
Return
-EINVAL: Runtime PM is disabled for dev. The usage counter is not incremented.1: Success; usage counter is incremented.0: dev was not in use; usage counter is not incremented.
-
int __pm_runtime_set_status(struct device *dev, unsigned int status)¶
Set runtime PM status of a device and clear errors.
Parameters
struct device *devDevice to handle.
unsigned int statusNew runtime PM status of the device.
Description
If runtime PM of the device is disabled or its power.runtime_error field is different from zero, the status may be changed either to RPM_ACTIVE, or to RPM_SUSPENDED, as long as that reflects the actual state of the device. However, if the device has a parent and the parent is not active, and the parent’s power.ignore_children flag is unset, the device’s status cannot be set to RPM_ACTIVE, so -EBUSY is returned in that case.
If successful, __pm_runtime_set_status() clears the power.runtime_error field
and the device parent’s counter of unsuspended children is modified to
reflect the new status. If the new status is RPM_SUSPENDED, an idle
notification request for the parent is submitted.
If dev has any suppliers (as reflected by device links to them), and status is RPM_ACTIVE, they will be activated upfront and if the activation of one of them fails, the status of dev will be changed to RPM_SUSPENDED (instead of the status value) and the suppliers will be deactivated on exit. The error returned by the failing supplier activation will be returned in that case.
Parameters
struct device *devDevice to handle.
Description
If the device has a pending resume request, resume it synchronously. For all other request types, cancel any queued request, and wait for running operations to complete.
Note that this is intentionally asymmetric, as it guarantees any queued asynchronous resume request will complete, but it may cancel asynchronous suspend requests.
Parameters
struct device *devDevice to handle.
Description
Enable runtime PM transitions for dev by decrementing its disable counter. Once the counter reaches zero, the PM core is permitted to execute runtime PM callbacks for dev as power conditions change.
Callers should ensure that the device’s runtime PM status accurately reflects
its physical hardware state (via pm_runtime_set_active() or
pm_runtime_set_suspended()) before enabling runtime PM.
-
int devm_pm_runtime_set_active_enabled(struct device *dev)¶
set_active version of devm_pm_runtime_enable.
Parameters
struct device *devDevice to handle.
Parameters
struct device *devDevice to handle.
NOTE
this will also handle calling pm_runtime_dont_use_autosuspend() for
you at driver exit time if needed.
-
int devm_pm_runtime_get_noresume(struct device *dev)¶
devres-enabled version of pm_runtime_get_noresume.
Parameters
struct device *devDevice to handle.
Parameters
struct device *devDevice to handle.
Description
Resume dev if already suspended and block runtime suspend of dev in such
a way that it can be unblocked via the /sys/devices/.../power/control
interface, or otherwise by calling pm_runtime_allow().
Calling this function many times in a row has the same effect as calling it once.
Parameters
struct device *devDevice to handle.
Description
Unblock runtime suspend of dev after it has been blocked by
pm_runtime_forbid() (for instance, if it has been blocked via the
/sys/devices/.../power/control interface), check if dev can be
suspended and suspend it in that case.
Calling this function many times in a row has the same effect as calling it once.
Parameters
struct device *devDevice to handle.
Description
Set the power.no_callbacks flag, which tells the PM core that this device is power-managed through its parent and has no runtime PM callbacks of its own. The runtime sysfs attributes will be removed.
Parameters
struct device *devDevice to handle
Description
Set the power.irq_safe flag, which tells the PM core that the
->runtime_suspend() and ->runtime_resume() callbacks for this device should
always be invoked with the spinlock held and interrupts disabled. It also
causes the parent’s usage counter to be permanently incremented, preventing
the parent from runtime suspending -- otherwise an irq-safe child might have
to wait for a non-irq-safe parent.
-
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)¶
Set a device’s autosuspend_delay value.
Parameters
struct device *devDevice to handle.
int delayValue of the new delay in milliseconds.
Description
Set the device’s power.autosuspend_delay value. If it changes to negative and the power.use_autosuspend flag is set, prevent runtime suspends. If it changes the other way, allow runtime suspends.
-
void __pm_runtime_use_autosuspend(struct device *dev, bool use)¶
Set a device’s use_autosuspend flag.
Parameters
struct device *devDevice to handle.
bool useNew value for use_autosuspend.
Description
Set the device’s power.use_autosuspend flag, and allow or prevent runtime suspends as needed.
Parameters
struct device *devDevice to suspend.
Description
Disable runtime PM so we safely can check the device’s runtime PM status and if it is active, invoke its ->runtime_suspend callback to suspend it and change its runtime PM status field to RPM_SUSPENDED. Also, if the device’s usage and children counters don’t indicate that the device was in use before the system-wide transition under way, decrement its parent’s children counter (if there is a parent). Keep runtime PM disabled to preserve the state unless we encounter errors.
Typically this function may be invoked from a system suspend callback to make
sure the device is put into low power state and it should only be used during
system-wide PM transitions to sleep states. It assumes that the analogous
pm_runtime_force_resume() will be used to resume the device.
Parameters
struct device *devDevice to resume.
Description
This function expects that either pm_runtime_force_suspend() has put the
device into a low-power state prior to calling it, or the device had been
runtime-suspended before the preceding system-wide suspend transition and it
was left in suspend during that transition.
The actions carried out by pm_runtime_force_suspend(), or by a runtime
suspend in general, are reversed and the device is brought back into full
power if it is expected to be used on system resume, which is the case when
its needs_force_resume flag is set or when its smart_suspend flag is set and
its runtime PM status is “active”.
In other cases, the resume is deferred to be managed via runtime PM.
Typically, this function may be invoked from a system resume callback.
-
void pm_suspend_ignore_children(struct device *dev, bool enable)¶
Set runtime PM behavior regarding children.
Parameters
struct device *devTarget device.
bool enableWhether or not to ignore possible dependencies on children.
Description
The dependencies of dev on its children will not be taken into account by
the runtime PM framework going forward if enable is true, or they will
be taken into account otherwise.
Parameters
struct device *devTarget device.
Parameters
struct device *devTarget device.
Description
Decrement the runtime PM usage counter of dev unless it is 0 already.
Parameters
struct device *devTarget device.
Description
Note that the return value of this function can only be trusted if it is called under the runtime PM lock of dev or under conditions in which runtime PM cannot be either disabled or enabled for dev and its runtime PM status cannot change.
Return
true: dev has runtime PM enabled and its status isRPM_SUSPENDED.false: Otherwise.
Parameters
struct device *devTarget device.
Description
Note that the return value of this function can only be trusted if it is called under the runtime PM lock of dev or under conditions in which runtime PM cannot be either disabled or enabled for dev and its runtime PM status cannot change.
Return
true: Runtime PM is disabled for dev or its status isRPM_ACTIVE.false: Otherwise.
Parameters
struct device *devTarget device.
Description
Note that the return value of this function can only be trusted if it is called under the runtime PM lock of dev or under conditions in which the runtime PM status of dev cannot change.
Return
true: Runtime PM status of dev isRPM_SUSPENDED.false: Otherwise.
Parameters
struct device *devTarget device.
Description
Note that the return value of this function can only be trusted if it is called under the runtime PM lock of dev or under conditions in which runtime PM cannot be either disabled or enabled for dev.
Return
true: Runtime PM is enabled for dev.false: Otherwise.
Parameters
struct device *devTarget device.
Description
Do not call this function outside system suspend/resume code paths.
Return
true: Runtime PM enabling is blocked for dev.false: Otherwise.
Parameters
struct device *devTarget device.
Return
true: dev is marked as having no runtime PM callbacks.false: Otherwise.
Parameters
struct device *devTarget device.
Description
Update the last access time of dev used by the runtime PM autosuspend
mechanism to the current time as returned by ktime_get_mono_fast_ns().
Parameters
struct device *devTarget device.
Return
true: dev has been marked as an “IRQ-safe” device, in which case its runtime PM callbacks can be expected to work correctly from interrupt handlers.false: Otherwise.
-
int pm_runtime_idle(struct device *dev)¶
Conditionally initiate autosuspend of a device or suspend it.
Parameters
struct device *devTarget device.
Description
Invoke the “idle check” callback of dev and, depending on its return value, initiate autosuspend of dev or suspend it (depending on whether or not autosuspend has been enabled for it).
Return
0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter non-zero, Runtime PM status change ongoing or device not inRPM_ACTIVEstate.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM idle and suspend callbacks.
Parameters
struct device *devTarget device.
Return
1: Success; device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM suspend callbacks.
-
int pm_runtime_autosuspend(struct device *dev)¶
Update the last access time and initiate autosuspend of a device.
Parameters
struct device *devTarget device.
Description
First update the last access time, then initiate autosuspend of dev or suspend it (depending on whether or not autosuspend is enabled for it) without engaging its “idle check” callback.
Return
1: Success; device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM suspend callbacks.
Parameters
struct device *devTarget device.
Return
1: Success; dev is alreadyRPM_ACTIVE.0: Success.Error code on failure.
Parameters
struct device *devTarget device.
Description
Asynchronously request the PM core to evaluate whether dev can be idled
or suspended, invoking its ->runtime_idle() callback if provided.
Return
0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter non-zero, Runtime PM status change ongoing or device not inRPM_ACTIVEstate.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.
Parameters
struct device *devTarget device.
Description
Asynchronously request the PM core to resume dev to RPM_ACTIVE state
without modifying its usage counter.
Return
1: Success; dev is alreadyRPM_ACTIVE.0: Success.Error code on failure.
Parameters
struct device *devTarget device.
Description
Update the last access time of dev and asynchronously request the PM core to suspend it after the autosuspend delay has elapsed.
Return
1: Success; device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.
Parameters
struct device *devTarget device.
Description
Increment the runtime PM usage counter of dev and, if the device is currently suspended, asynchronously request the PM core to resume it.
Return
1: Success; dev is alreadyRPM_ACTIVE.0: Success; runtime-resume was queued.Error code on failure.
Parameters
struct device *devTarget device.
Description
Bump up the runtime PM usage counter of dev and carry out runtime-resume of it synchronously.
Note that the runtime PM usage counter of dev remains incremented in all
cases, even if it returns an error code. Consider using
pm_runtime_resume_and_get() instead, especially if the return value is
checked by the caller, as this is likely to result in cleaner code.
Return
1: Success; dev is alreadyRPM_ACTIVE.0: Success.Error code on failure.
Parameters
struct device *devTarget device.
Description
Resume dev synchronously and if that is successful, increment its runtime PM usage counter.
Return
0: Success; dev is active and its usage counter has been incremented.Negative error code on failure; usage counter is unchanged.
-
void pm_runtime_put(struct device *dev)¶
Drop device usage counter and request asynchronous idle check.
Parameters
struct device *devTarget device.
Description
Decrement the runtime PM usage counter of dev. If the counter reaches zero and the device has no active child dependencies, asynchronously request the PM core to idle or suspend the device.
-
int __pm_runtime_put_autosuspend(struct device *dev)¶
Drop device usage counter and queue autosuspend if 0.
Parameters
struct device *devTarget device.
Description
Decrement the runtime PM usage counter of dev and if it turns out to be
equal to 0, queue up a work item for dev like in pm_request_autosuspend().
Return
1: Success. Usage counter dropped to zero, but device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter became non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.
-
int pm_runtime_put_autosuspend(struct device *dev)¶
Update the last access time, drop usage counter and request autosuspend.
Parameters
struct device *devTarget device.
Description
Update the last access time of dev and decrement its runtime PM usage counter. If the counter drops to zero, asynchronously request the PM core to suspend the device once its autosuspend delay has elapsed.
Return
1: Success. Usage counter dropped to zero, but device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter became non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.
Parameters
struct device *devTarget device.
Description
Decrement the runtime PM usage counter of dev. If the counter drops to zero, synchronously evaluate and trigger idle/suspend handling.
Note that this does not update the last access time, but it does respect
existing autosuspend timers. If dev uses autosuspend, consider using
pm_runtime_put_sync_autosuspend() or pm_runtime_put_sync_suspend() instead.
The runtime PM usage counter of dev remains decremented in all cases, even if it returns an error code.
Return
1: Success. Usage counter dropped to zero, but device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter became non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM suspend callbacks.
Parameters
struct device *devTarget device.
Description
Decrement the runtime PM usage counter of dev. If the counter drops to zero, suspend the device synchronously.
This API differs from pm_runtime_put_sync() and
pm_runtime_put_sync_autosuspend() in that it ignores any outstanding
autosuspend delays.
The runtime PM usage counter of dev remains decremented in all cases, even if it returns an error code.
Return
1: Success. Usage counter dropped to zero, but device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter became non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM suspend callbacks.
-
int pm_runtime_put_sync_autosuspend(struct device *dev)¶
Update the last access time of a device, drop device usage counter and autosuspend if 0.
Parameters
struct device *devTarget device.
Description
Update the last access time of dev and decrement its runtime PM usage counter. If the counter drops to zero, synchronously suspend the device (or schedule autosuspend if the delay has not elapsed).
Prefer this API over pm_runtime_put_sync() for devices that use autosuspend.
The runtime PM usage counter of dev remains decremented in all cases, even if it returns an error code.
Return
1: Success. Usage counter dropped to zero, but device was already suspended.0: Success.-EINVAL: Runtime PM error.-EACCES: Runtime PM disabled.-EAGAIN: Runtime PM usage counter became non-zero or Runtime PM status change ongoing.-EBUSY: Runtime PM child_count non-zero.-EPERM: Device PM QoS resume latency 0.-EINPROGRESS: Suspend already in progress.-ENOSYS:CONFIG_PMnot enabled.Other values and conditions for the above values are possible as returned by Runtime PM suspend callbacks.
Parameters
struct device *devTarget device.
Description
Set the runtime PM status of dev to RPM_ACTIVE and ensure that its
dependencies will be taken into account. Also clear the device’s error
status (dev->power.runtime_error).
It is only valid to call this function if runtime PM is disabled or if dev->power.runtime_error is set.
This will fail if suppliers cannot be resumed, or if the parent is not in the correct state.
Return
0: Success.Error code on failure.
-
int pm_runtime_set_suspended(struct device *dev)¶
Set runtime PM status to “suspended” and clear errors.
Parameters
struct device *devTarget device.
Description
Set the runtime PM status of dev to RPM_SUSPENDED and ensure that its
dependencies will be taken into account. Also clear the device’s error
status (dev->power.runtime_error).
It is only valid to call this function if runtime PM is disabled or if dev->power.runtime_error is set.
Return
0: Success.Error code on failure.
Parameters
struct device *devTarget device.
Description
Prevent the runtime PM framework from working with dev by incrementing its “disable” counter.
If the counter is zero when this function runs and there is a pending runtime resume request for dev, it will be resumed. If the counter is still zero at that point, this function cancels all pending runtime PM requests for dev and waits for its runtime PM operations to complete (if any).
For each invocation of this function for dev, there must be a matching
pm_runtime_enable() call, so that runtime PM is eventually enabled for it
again.
Parameters
struct device *devTarget device.
Description
Allow the runtime PM autosuspend mechanism to be used for dev whenever requested (or “autosuspend” will be handled as direct runtime-suspend for it).
NOTE
It’s important to undo this with pm_runtime_dont_use_autosuspend()
at driver exit time unless your driver initially enabled pm_runtime
with devm_pm_runtime_enable() (which handles it for you).
Parameters
struct device *devTarget device.
Description
Prevent the runtime PM autosuspend mechanism from being used for dev which means that “autosuspend” will be handled as direct runtime-suspend for it going forward.
It is safe to execute the following helper functions from interrupt context:
If pm_runtime_irq_safe() has been called for a device then the following helper
functions may also be used in interrupt context:
5. Runtime PM Initialization, Device Probing and Removal¶
Initially, the runtime PM is disabled for all devices, which means that the
majority of the runtime PM helper functions described in Section 4 will
return -EACCES until pm_runtime_enable() is called for the device.
In addition to that, the initial runtime PM status of all devices is
‘suspended’, but it need not reflect the actual physical state of the device.
Thus, if the device is initially active (i.e. it is able to process I/O), its
runtime PM status must be changed to ‘active’, with the help of
pm_runtime_set_active(), before pm_runtime_enable() is called for the device.
However, if the device has a parent and the parent’s runtime PM is enabled,
calling pm_runtime_set_active() for the device will affect the parent, unless
the parent’s ‘power.ignore_children’ flag is set. Namely, in that case the
parent won’t be able to suspend at run time, using the PM core’s helper
functions, as long as the child’s status is ‘active’, even if the child’s
runtime PM is still disabled (i.e. pm_runtime_enable() hasn’t been called for
the child yet or pm_runtime_disable() has been called for it). For this reason,
once pm_runtime_set_active() has been called for the device, pm_runtime_enable()
should be called for it too as soon as reasonably possible or its runtime PM
status should be changed back to ‘suspended’ with the help of
pm_runtime_set_suspended().
If the default initial runtime PM status of the device (i.e. ‘suspended’)
reflects the actual state of the device, its bus type’s or its driver’s
->probe() callback will likely need to wake it up using one of the PM core’s
helper functions described in Section 4. In that case, pm_runtime_resume()
should be used. Of course, for this purpose the device’s runtime PM has to be
enabled earlier by calling pm_runtime_enable().
Note, if the device may execute pm_runtime calls during the probe (such as
if it is registered with a subsystem that may call back in) then the
pm_runtime_resume_and_get() call paired with a pm_runtime_put() call will be
appropriate to ensure that the device is not put back to sleep during the
probe. This can happen with systems such as the network device layer.
It may be desirable to suspend the device once ->probe() has finished.
Therefore the driver core uses the asynchronous pm_request_idle() to submit a
request to execute the subsystem-level idle callback for the device at that
time. A driver that makes use of the runtime autosuspend feature may want to
update the last busy mark before returning from ->probe().
Moreover, the driver core prevents runtime PM callbacks from racing with the bus
notifier callback in __device_release_driver(), which is necessary because the
notifier is used by some subsystems to carry out operations affecting the
runtime PM functionality. It does so by calling pm_runtime_get_sync() before
driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications. This
resumes the device if it’s in the suspended state and prevents it from
being suspended again while those routines are being executed.
To allow bus types and drivers to put devices into the suspended state by
calling pm_runtime_suspend() from their ->remove() routines, the driver core
executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
notifications in __device_release_driver(). This requires bus types and
drivers to make their ->remove() callbacks avoid races with runtime PM directly,
but it also allows more flexibility in the handling of devices during the
removal of their drivers.
Drivers in ->remove() callback should undo the runtime PM changes done
in ->probe(). Usually this means calling pm_runtime_disable(),
pm_runtime_dont_use_autosuspend() etc. Alternatively, drivers can use
devm_pm_runtime_enable() during probe, which automatically takes care of
calling pm_runtime_disable() and pm_runtime_dont_use_autosuspend() upon driver
detachment.
The user space can effectively disallow the driver of the device to power manage
it at run time by changing the value of its /sys/devices/.../power/control
attribute to “on”, which causes pm_runtime_forbid() to be called. In principle,
this mechanism may also be used by the driver to effectively turn off the
runtime power management of the device until the user space turns it on.
Namely, during the initialization the driver can make sure that the runtime PM
status of the device is ‘active’ and call pm_runtime_forbid(). It should be
noted, however, that if the user space has already intentionally changed the
value of /sys/devices/.../power/control to “auto” to allow the driver to power
manage the device at run time, the driver may confuse it by using
pm_runtime_forbid() this way.
6. Runtime PM and System Sleep¶
Runtime PM and system sleep (i.e., system suspend and hibernation, also known as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of ways. If a device is active when a system sleep starts, everything is straightforward. But what should happen if the device is already suspended?
The device may have different wake-up settings for runtime PM and system sleep. For example, remote wake-up may be enabled for runtime suspend but disallowed for system sleep (device_may_wakeup(dev) returns ‘false’). When this happens, the subsystem-level system suspend callback is responsible for changing the device’s wake-up setting (it may leave that to the device driver’s system suspend routine). It may be necessary to resume the device and suspend it again in order to do so. The same is true if the driver uses different power levels or other settings for runtime suspend and system sleep.
During system resume, the simplest approach is to bring all devices back to full power, even if they had been suspended before the system suspend began. There are several reasons for this, including:
The device might need to switch power levels, wake-up settings, etc.
Remote wake-up events might have been lost by the firmware.
The device’s children may need the device to be at full power in order to resume themselves.
The driver’s idea of the device state may not agree with the device’s physical state. This can happen during resume from hibernation.
The device might need to be reset.
Even though the device was suspended, if its usage counter was > 0 then most likely it would need a runtime resume in the near future anyway.
If the device had been suspended before the system suspend began and it’s brought back to full power during resume, then its runtime PM status will have to be updated to reflect the actual post-system sleep status. The way to do this is:
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
The PM core always increments the runtime usage counter before calling the
->suspend() callback and decrements it after calling the ->resume() callback.
Hence disabling runtime PM temporarily like this will not cause any runtime
suspend attempts to be permanently lost. If the usage count goes to zero
following the return of the ->resume() callback, the ->runtime_idle() callback
will be invoked as usual.
On some systems, however, system sleep is not entered through a global firmware or hardware operation. Instead, all hardware components are put into low-power states directly by the kernel in a coordinated way. Then, the system sleep state effectively follows from the states the hardware components end up in and the system is woken up from that state by a hardware interrupt or a similar mechanism entirely under the kernel’s control. As a result, the kernel never gives control away and the states of all devices during resume are precisely known to it. If that is the case and none of the situations listed above takes place (in particular, if the system is not waking up from hibernation), it may be more efficient to leave the devices that had been suspended before the system suspend began in the suspended state.
To this end, the PM core provides a mechanism allowing some coordination between
different levels of device hierarchy. Namely, if a system suspend .prepare()
callback returns a positive number for a device, that indicates to the PM core
that the device appears to be runtime-suspended and its state is fine, so it
may be left in runtime suspend provided that all of its descendants are also
left in runtime suspend. If that happens, the PM core will not execute any
system suspend and resume callbacks for all of those devices, except for the
.complete() callback, which is then entirely responsible for handling the device
as appropriate. This only applies to system suspend transitions that are not
related to hibernation (see Device Power Management Basics for more
information).
The PM core does its best to reduce the probability of race conditions between the runtime PM and system suspend/resume (and hibernation) callbacks by carrying out the following operations:
During system suspend
pm_runtime_get_noresume()is called for every device right before executing the subsystem-level .prepare()callback for it andpm_runtime_barrier()is called for every device right before executing the subsystem-level .suspend()callback for it. In addition to that, the PM core disables runtime PM for every device right before executing the subsystem-level .suspend_late()callback for it.During system resume
pm_runtime_enable()andpm_runtime_put()are called for every device right after executing the subsystem-level .resume_early()callback and right after executing the subsystem-level .complete()callback for it, respectively.
7. Generic subsystem callbacks¶
Subsystems may wish to conserve code space by using the set of generic power management callbacks provided by the PM core, defined in drivers/base/power/generic_ops.c:
-
int pm_generic_runtime_suspend(struct device *dev)¶
Generic runtime suspend callback for subsystems.
Parameters
struct device *devDevice to suspend.
Description
If PM operations are defined for the dev’s driver and they include
->runtime_suspend(), execute it and return its error code. Otherwise,
return 0.
Parameters
struct device *devDevice to resume.
Description
If PM operations are defined for the dev’s driver and they include
->runtime_resume(), execute it and return its error code. Otherwise,
return 0.
Parameters
struct device *devDevice to suspend.
Parameters
struct device *devDevice to suspend.
Parameters
struct device *devDevice to suspend.
Parameters
struct device *devDevice to freeze.
Parameters
struct device *devDevice to freeze.
Parameters
struct device *devDevice to handle.
Parameters
struct device *devDevice to handle.
Parameters
struct device *devDevice to handle.
Parameters
struct device *devDevice to thaw.
Parameters
struct device *devDevice to thaw.
Parameters
struct device *devDevice to resume.
Parameters
struct device *devDevice to resume.
Parameters
struct device *devDevice to resume.
Parameters
struct device *devDevice to restore.
Parameters
struct device *devDevice to resume.
Parameters
struct device *devDevice to restore.
These functions are the defaults used by the PM core if a subsystem doesn’t
provide its own callbacks for ->runtime_idle(), ->runtime_suspend(),
->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(),
->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(),
->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() in the
subsystem-level dev_pm_ops structure.
Device drivers that wish to use the same function as a system suspend, freeze,
poweroff and runtime suspend callback, and similarly for system resume, thaw,
restore, and runtime resume, can achieve similar behaviour with the help of the
DEFINE_RUNTIME_DEV_PM_OPS() macro defined in include/linux/pm_runtime.h
(possibly setting its last argument to NULL).
8. “No-Callback” Devices¶
Some “devices” are only logical sub-devices of their parent and cannot be
power-managed on their own. (The prototype example is a USB interface. Entire
USB devices can go into low-power mode or send wake-up requests, but neither is
possible for individual interfaces.) The drivers for these devices have no
need of runtime PM callbacks; if the callbacks did exist, ->runtime_suspend()
and ->runtime_resume() would always return 0 without doing anything else and
->runtime_idle() would always call pm_runtime_suspend().
Subsystems can tell the PM core about these devices by calling
pm_runtime_no_callbacks(). This should be done after the device structure is
initialized and before it is registered (although after device registration is
also okay). The routine will set the device’s power.no_callbacks flag and
prevent the non-debugging runtime PM sysfs attributes from being created.
When power.no_callbacks is set, the PM core will not invoke the
->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
Instead it will assume that suspends and resumes always succeed and that idle
devices should be suspended.
As a consequence, the PM core will never directly inform the device’s subsystem or driver about runtime power changes. Instead, the driver for the device’s parent must take responsibility for telling the device’s driver when the parent’s power state changes.
Note that, in some cases it may not be desirable for subsystems/drivers to call
pm_runtime_no_callbacks() for their devices. This could be because a subset of
the runtime PM callbacks needs to be implemented, a platform dependent PM
domain could get attached to the device or that the device is power managed
through a supplier device link. For these reasons and to avoid boilerplate code
in subsystems/drivers, the PM core allows runtime PM callbacks to be
unassigned. More precisely, if a callback pointer is NULL, the PM core will act
as though there was a callback and it returned 0.
9. Autosuspend, or automatically-delayed suspends¶
Changing a device’s power state isn’t free; it requires both time and energy. A device should be put in a low-power state only when there’s some reason to think it will remain in that state for a substantial time. A common heuristic says that a device which hasn’t been used for a while is liable to remain unused; following this advice, drivers should not allow devices to be suspended at runtime until they have been inactive for some minimum period. Even when the heuristic ends up being non-optimal, it will still prevent devices from “bouncing” too rapidly between low-power and full-power states.
The term “autosuspend” is an historical remnant. It doesn’t mean that the device is automatically suspended (the subsystem or driver still has to call the appropriate PM routines); rather it means that runtime suspends will automatically be delayed until the desired period of inactivity has elapsed.
Inactivity is determined based on the power.last_busy field. The desired length
of the inactivity period is a matter of policy. Subsystems can set this length
initially by calling pm_runtime_set_autosuspend_delay(), but after device
registration the length should be controlled by user space, using the
/sys/devices/.../power/autosuspend_delay_ms attribute.
In order to use autosuspend, subsystems or drivers must call
pm_runtime_use_autosuspend() (preferably before registering the device), and
thereafter they should use the various *_autosuspend() helper functions
instead of the non-autosuspend counterparts:
Instead of: pm_runtime_suspend use: pm_runtime_autosuspend;
Instead of: pm_schedule_suspend use: pm_request_autosuspend;
Instead of: pm_runtime_put use: pm_runtime_put_autosuspend;
Instead of: pm_runtime_put_sync use: pm_runtime_put_sync_autosuspend.
Drivers may also continue to use the non-autosuspend helper functions; they
will behave normally, which means sometimes taking the autosuspend delay into
account (see pm_runtime_idle()). The autosuspend variants of the functions also
call pm_runtime_mark_last_busy().
Under some circumstances a driver or subsystem may want to prevent a device
from autosuspending immediately, even though the usage counter is zero and the
autosuspend delay time has expired. If the ->runtime_suspend() callback
returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is
in the future (as it normally would be if the callback invoked
pm_runtime_mark_last_busy()), the PM core will automatically reschedule the
autosuspend. The ->runtime_suspend() callback can’t do this rescheduling
itself because no suspend requests of any kind are accepted while the device is
suspending (i.e., while the callback is running).
The implementation is well suited for asynchronous use in interrupt contexts.
However such use inevitably involves races, because the PM core can’t
synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
This synchronization must be handled by the driver, using its private lock.
Here is a schematic pseudo-code example:
foo_read_or_write(struct foo_priv *foo, void *data)
{
lock(&foo->private_lock);
add_request_to_io_queue(foo, data);
if (foo->num_pending_requests++ == 0)
pm_runtime_get(&foo->dev);
if (!foo->is_suspended)
foo_process_next_request(foo);
unlock(&foo->private_lock);
}
foo_io_completion(struct foo_priv *foo, void *req)
{
lock(&foo->private_lock);
if (--foo->num_pending_requests == 0)
pm_runtime_put_autosuspend(&foo->dev);
else
foo_process_next_request(foo);
unlock(&foo->private_lock);
/* Send req result back to the user ... */
}
int foo_runtime_suspend(struct device *dev)
{
struct foo_priv *foo = container_of(dev, ...);
int ret = 0;
lock(&foo->private_lock);
if (foo->num_pending_requests > 0) {
ret = -EBUSY;
} else {
/* ... suspend the device ... */
foo->is_suspended = 1;
}
unlock(&foo->private_lock);
return ret;
}
int foo_runtime_resume(struct device *dev)
{
struct foo_priv *foo = container_of(dev, ...);
lock(&foo->private_lock);
/* ... resume the device ... */
foo->is_suspended = 0;
pm_runtime_mark_last_busy(&foo->dev);
if (foo->num_pending_requests > 0)
foo_process_next_request(foo);
unlock(&foo->private_lock);
return 0;
}
The important point is that after foo_io_completion() asks for an autosuspend,
the foo_runtime_suspend() callback may race with foo_read_or_write().
Therefore foo_runtime_suspend() has to check whether there are any pending I/O
requests (while holding the private lock) before allowing the suspend to
proceed.
In addition, the power.autosuspend_delay field can be changed by user space at
any time. If a driver cares about this, it can call
pm_runtime_autosuspend_expiration() from within the ->runtime_suspend()
callback while holding its private lock. If the function returns a nonzero
value then the delay has not yet expired and the callback should return
-EAGAIN.