* [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs
@ 2026-09-30 2:49 Brian Norris
2026-09-30 2:49 ` [PATCH v3 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
The runtime PM documentation could use some improvements and additions,
to help guide people less familiar with the main runtime PM concepts and
its internal implementation details.
v1 is here:
https://lore.kernel.org/all/20260904212000.4167880-1-briannorris@chromium.org/
v2 is here:
https://lore.kernel.org/all/20260923174711.1283986-1-briannorris@chromium.org/
The first part of the v1 series has already been applied. For the
remaining work:
- Formatting and clarity improvements.
- Clarifying core concepts in the Introduction. (Pretty much all new
readers I encounter have a hard time with the difference between
"enabled", "allowed", and "active".)
- Adding Example driver patterns -- because the API is so large and
complicated, it can help to try to walk people through standard
practices, and what everything means in context.
I tried to keep some of the larger changes toward the end, to hopefully
make it easier to rework or reject them while cherry-picking some of the
easier stuff from the first part of the series.
Feel free to add suggestions! Within reason, I'm open to tackling more
here, as I think many people have many valid perspectives on exactly why
and how the docs do or don't serve people well today. Or I can tackle
less, if you think some of my choices are not improvements.
Some possible follow-ups I'm toying with:
* Slimming down the API might be better than heavily documenting it. A
smaller API is a more digestible API.
My only concrete next step: drop __pm_runtime_put_autosuspend(). Its
last user is nearly gone:
https://lore.kernel.org/all/20260806-smmu-rpm-v4-1-8183d007331c@oss.qualcomm.com/
I could also see deprecating one of
pm_runtime_put_sync{,_suspend,_autosuspend}(). They all do slightly
different things, but I'm not sure every difference is actually fully
intentional (or at least, not necessary).
* Tweaking some of the behavior on pm_runtime_barrier(). Today, it's
very asymmetric, as it prefers resume. But I believe there may be
value in making it flush (not just cancel) pending suspend too. That
may be in a future proposal; for now, I just try to make its
asymmetry more clear in the docs.
* Sand down some more rough edges on return codes. For example, it's
very difficult to get any useful meaning out of pm_runtime_put_sync()
return codes. There's a high chance that anyone trying to treat
return codes as errors is inviting bugs. (Is -EAGAIN a failure?)
Of course, the answer there is not "document it better" -- we can
make it easier to use.
* Adjust the way devm_pm_runtime_enable() works, specifically for
remove()/teardown. Currently, this is very hard to use correctly --
some common driver patterns may assume that a device will tear down
while RPM_SUSPENDED; but that's not actually guaranteed. Notably,
this makes some of the "Examples" section fairly tricky/subtle.
Regards,
Brian
Changes in v3:
* Misc formatting improvements
* Rewrite Examples to avoid devm_* at first, to highlight correct
approaches
* Include error-handling and remove() in any probe() Examples
* Advise more caution when using devm_*, as ordering issues are subtle
Changes in v2:
* Major rework on Introduction section, especially regarding "enabled"
and "active"
* Add appropriate teardown to "Probe with Hardware Powered Off"
Example, as the remove() + power-off behavior is subtle here, and
easy to get wrong
* Drop changes that are already applied
* Add a few new fix patches, noticed while reviewing the rest
* Move Introduction patch near the end of the series, as it is a likely
target for further discussion and modification.
* Correct Ulf's email address
* CC linux-doc
Brian Norris (8):
PM: runtime: Correct pm_runtime_autosuspend_expiration() doc
PM: runtime: More kerneldoc formatting
PM: runtime: Misc improvements to runtime_pm.rst
PM: runtime: Add "Section" hyperlinks
PM: runtime: Clarify ->runtime_idle() callback return value handling
PM: runtime: Clarify driver callback expectations and structure
Section 2
PM: runtime: Expand introduction with core concepts and structure
PM: runtime: Add Example Driver Patterns section
Documentation/power/runtime_pm.rst | 676 +++++++++++++++++++++++++++--
drivers/base/power/runtime.c | 12 +-
2 files changed, 633 insertions(+), 55 deletions(-)
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 2/8] PM: runtime: More kerneldoc formatting Brian Norris
` (7 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
The "adjusted to be nonzero" comment may be a relic from when this API
previously used jiffies, although I'm not quite sure about that either.
In any case, it doesn't seem correct today.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
(no changes since v2)
Changes in v2:
* New in v2
drivers/base/power/runtime.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index bb008dfe85a1..7e75f6d5df07 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -169,7 +169,7 @@ static void pm_runtime_cancel_pending(struct device *dev)
* 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 (adjusted to be nonzero).
+ * 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.
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 2/8] PM: runtime: More kerneldoc formatting
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-30 2:49 ` [PATCH v3 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
` (6 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
In taking another pass at these docs, I found some more inconsistencies.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
Changes in v3:
* Wrap/shorten differently
* Resolve a few other inconsistencies with a similar pattern
Changes in v2:
* New in v2
drivers/base/power/runtime.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 7e75f6d5df07..00d1981763b6 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1254,12 +1254,11 @@ static int pm_runtime_get_conditional(struct device *dev, bool ign_usage_count)
}
/**
- * pm_runtime_get_if_active - Bump up runtime PM usage counter if the device is
- * in active state
+ * pm_runtime_get_if_active - Conditionally bump up runtime PM usage counter.
* @dev: Target device.
*
* Increment the runtime PM usage counter of @dev if its runtime PM status is
- * already %RPM_ACTIVE
+ * already %RPM_ACTIVE.
*
* Return:
* * %-EINVAL: Runtime PM is disabled for @dev. The usage counter is not incremented.
@@ -1607,7 +1606,6 @@ static void pm_runtime_set_suspended_action(void *data)
/**
* devm_pm_runtime_set_active_enabled - set_active version of devm_pm_runtime_enable.
- *
* @dev: Device to handle.
*/
int devm_pm_runtime_set_active_enabled(struct device *dev)
@@ -1634,11 +1632,10 @@ static void pm_runtime_disable_action(void *data)
/**
* devm_pm_runtime_enable - devres-enabled version of pm_runtime_enable.
+ * @dev: Device to handle.
*
* NOTE: this will also handle calling pm_runtime_dont_use_autosuspend() for
* you at driver exit time if needed.
- *
- * @dev: Device to handle.
*/
int devm_pm_runtime_enable(struct device *dev)
{
@@ -1655,7 +1652,6 @@ static void pm_runtime_put_noidle_action(void *data)
/**
* devm_pm_runtime_get_noresume - devres-enabled version of pm_runtime_get_noresume.
- *
* @dev: Device to handle.
*/
int devm_pm_runtime_get_noresume(struct device *dev)
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 3/8] PM: runtime: Misc improvements to runtime_pm.rst
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-30 2:49 ` [PATCH v3 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
2026-09-30 2:49 ` [PATCH v3 2/8] PM: runtime: More kerneldoc formatting Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
There are several small errors and omissions, as well as new updates
(pm_runtime_resume_and_get(), devm_pm_runtime_enable()) we should
incorporate.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
devm_pm_runtime_enable() can be a tricky API to use correctly. I mention
it here for completeness, but see the Example updates in patch 8, which
help describe its pitfalls.
Changes in v3:
* add pm_runtime_get_if_active(), pm_runtime_get_if_in_use() to
interrupt-safe list
Documentation/power/runtime_pm.rst | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 39fdeeda7a1e..59b634fd6829 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -229,6 +229,8 @@ It is safe to execute the following helper functions from interrupt context:
- pm_request_resume()
- pm_runtime_get_noresume()
- pm_runtime_get()
+- pm_runtime_get_if_active()
+- pm_runtime_get_if_in_use()
- pm_runtime_put_noidle()
- pm_runtime_put()
- pm_runtime_put_autosuspend()
@@ -238,6 +240,9 @@ It is safe to execute the following helper functions from interrupt context:
- pm_runtime_set_active()
- pm_runtime_set_suspended()
- pm_runtime_suspended()
+- pm_runtime_active()
+- pm_runtime_status_suspended()
+- pm_runtime_enabled()
- pm_runtime_mark_last_busy()
- pm_runtime_autosuspend_expiration()
@@ -249,6 +254,7 @@ functions may also be used in interrupt context:
- pm_runtime_autosuspend()
- pm_runtime_resume()
- pm_runtime_get_sync()
+- pm_runtime_resume_and_get()
- pm_runtime_put_sync()
- pm_runtime_put_sync_suspend()
- pm_runtime_put_sync_autosuspend()
@@ -258,7 +264,7 @@ functions may also be used in interrupt context:
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
--EAGAIN until pm_runtime_enable() is called for the device.
+-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.
@@ -287,7 +293,7 @@ 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_get_sync() call paired with a pm_runtime_put() call will be
+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.
@@ -315,7 +321,10 @@ 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.
+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
@@ -426,7 +435,7 @@ out the following operations:
Subsystems may wish to conserve code space by using the set of generic power
management callbacks provided by the PM core, defined in
-driver/base/power/generic_ops.c:
+drivers/base/power/generic_ops.c:
.. kernel-doc:: drivers/base/power/generic_ops.c
:export:
@@ -441,8 +450,8 @@ 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() defined in include/linux/pm_runtime.h (possibly setting its
-last argument to NULL).
+DEFINE_RUNTIME_DEV_PM_OPS() macro defined in include/linux/pm_runtime.h
+(possibly setting its last argument to NULL).
8. "No-Callback" Devices
========================
@@ -505,7 +514,7 @@ registration the length should be controlled by user space, using the
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
+thereafter they should use the various \*_autosuspend() helper functions
instead of the non-autosuspend counterparts::
Instead of: pm_runtime_suspend use: pm_runtime_autosuspend;
@@ -515,7 +524,7 @@ instead of the non-autosuspend counterparts::
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
+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
@@ -558,7 +567,7 @@ Here is a schematic pseudo-code example::
int foo_runtime_suspend(struct device *dev)
{
- struct foo_priv foo = container_of(dev, ...);
+ struct foo_priv *foo = container_of(dev, ...);
int ret = 0;
lock(&foo->private_lock);
@@ -574,7 +583,7 @@ Here is a schematic pseudo-code example::
int foo_runtime_resume(struct device *dev)
{
- struct foo_priv foo = container_of(dev, ...);
+ struct foo_priv *foo = container_of(dev, ...);
lock(&foo->private_lock);
/* ... resume the device ... */
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 4/8] PM: runtime: Add "Section" hyperlinks
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (2 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
Add reStructuredText targets for each section, and use them throughout
to make the generated HTML more navigable.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
(no changes since v2)
Changes in v2:
* Rebase to put this earlier in the series
Documentation/power/runtime_pm.rst | 48 ++++++++++++++++++++----------
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 59b634fd6829..8e93766bdf99 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -8,6 +8,8 @@ Runtime Power Management Framework for I/O Devices
(C) 2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+.. _Section 1:
+
1. Introduction
===============
@@ -37,6 +39,8 @@ 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.
+.. _Section 2:
+
2. Device Runtime PM Callbacks
==============================
@@ -80,8 +84,8 @@ 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.
+listed at the end of `Section 4`_ may be used for that device within an
+interrupt handler or generally in an atomic context.
The subsystem-level suspend callback, if present, is _entirely_ _responsible_
for handling the suspend of the device as appropriate, which may, but need not
@@ -105,9 +109,9 @@ knows what to do to handle the device).
* 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).
+ 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
@@ -132,10 +136,10 @@ what to do to handle the device).
'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).
+ 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
@@ -158,9 +162,9 @@ call to pm_runtime_autosuspend(). To prevent this (for example, if the callback
routine has started a delayed suspend), the routine must return a non-zero
value. Negative error return codes are ignored by the PM core.
-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 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:
(1) The callbacks are mutually exclusive (e.g. it is forbidden to execute
->runtime_suspend() in parallel with ->runtime_resume() or with another
@@ -200,6 +204,8 @@ rules:
scheduled requests to execute the other callbacks for the same device,
except for scheduled autosuspends.
+.. _Section 3:
+
3. Runtime PM Device Fields
===========================
@@ -210,6 +216,8 @@ state.
.. kernel-doc:: include/linux/pm.h
:identifiers: dev_pm_info
+.. _Section 4:
+
4. Runtime PM Device Helper Functions
=====================================
@@ -259,12 +267,14 @@ functions may also be used in interrupt context:
- pm_runtime_put_sync_suspend()
- pm_runtime_put_sync_autosuspend()
+.. _Section 5:
+
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.
+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.
@@ -287,7 +297,7 @@ 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()
+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().
@@ -338,6 +348,8 @@ 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.
+.. _Section 6:
+
6. Runtime PM and System Sleep
==============================
@@ -430,6 +442,8 @@ out the following operations:
callback and right after executing the subsystem-level .complete() callback
for it, respectively.
+.. _Section 7:
+
7. Generic subsystem callbacks
==============================
@@ -453,6 +467,8 @@ 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).
+.. _Section 8:
+
8. "No-Callback" Devices
========================
@@ -489,6 +505,8 @@ 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.
+.. _Section 9:
+
9. Autosuspend, or automatically-delayed suspends
=================================================
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (3 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
This doc says "Negative error return codes are ignored by the PM core"
for ->runtime_idle(). This is misleading: any non-zero return value
(including negative error codes such as -EBUSY or -EAGAIN) tells the PM
core to abort automatic suspension of the device, which is commonly used
by subsystems to prevent immediate runtime suspend.
Clarify that unlike ->runtime_suspend() and ->runtime_resume(), the PM core
does not treat negative return values from ->runtime_idle() as a fatal
device error, and that any non-zero value stops the PM core from
suspending the device.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
(no changes since v1)
Documentation/power/runtime_pm.rst | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 8e93766bdf99..6fe20ad8d3d9 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -158,9 +158,14 @@ 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 (for example, if the callback
-routine has started a delayed suspend), the routine must return a non-zero
-value. Negative error return codes are ignored by the PM core.
+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.
The helper functions provided by the PM core, described in `Section 4`_,
guarantee that the following constraints are met with respect to runtime PM
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (4 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 2:49 ` [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
Section 2 describes the three runtime callbacks, but:
1) it's fairly dense to read (150+ lines); and
2) it glosses over a big point -- that it's uncommon for drivers to
implement ->runtime_idle()
Add a note up-front to help direct the reader about #2, and add headings
to try to break up the text a bit.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
(no changes since v1)
Documentation/power/runtime_pm.rst | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 6fe20ad8d3d9..68903d93a3e7 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -54,6 +54,14 @@ There are three device runtime PM callbacks defined in 'struct dev_pm_ops'::
...
};
+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:
@@ -87,6 +95,9 @@ 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
@@ -167,6 +178,9 @@ return a non-zero value (typically -EBUSY or -EAGAIN). Unlike
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:
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (5 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 15:41 ` Rafael J. Wysocki (Intel)
2026-09-30 15:44 ` Ulf Hansson
2026-09-30 2:49 ` [PATCH v3 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
2026-09-30 12:56 ` [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Rafael J. Wysocki (Intel)
8 siblings, 2 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
I commonly see people have difficulty learning how runtime PM works
because of the following key points [*]:
1) there are several boolean concepts in runtime PM, with somewhat
similar meanings:
enabled / disabled
active / suspended
allowed / forbidden
2) if these concepts are documented at all, they're scattered across
the kerneldoc or Documentation/
3) the runtime_pm.rst docs don't make any attempt to ease a reader into
understanding the concepts, and instead jump straight into how it's
implemented (queues, 'struct device' fields, helpers).
Let's try to remedy this a bit by discussing the core concepts and
highlights at the top of the introduction, and introduce a few
sub-headings, so it's easier to navigate different aspects of the
introduction.
While shuffling the intro around, I also see that the existing text
largely mirrors the layout of the following sections (2, 3, and 4), but
does so out of order. Reorder those, and point to section numbers.
[*] In addition to API complexity. I count 61 pm_*() helpers, 7 of which
are variations of put() and 8 of which are variations of get().
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
(no changes since v2)
Changes in v2:
Address review feedback around descriptions of "enabled" and "active". I
know not every point of discussion was settled, but I hope this updated
version resolves many of them and provides a better basis for further
improvement.
* Avoid calling enabled and active "orthogonal"
* Describe more of their inter-relationship
* Prioritize talking about "enabled" first, since that's the first
concept a reader should know about
* Brief mentions of parent/child and supplier/consumer, and dependency
handling
* Other tweaks
Documentation/power/runtime_pm.rst | 103 +++++++++++++++++++++++------
1 file changed, 84 insertions(+), 19 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 68903d93a3e7..c63fbf0ff862 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -13,31 +13,96 @@ Runtime Power Management Framework for I/O Devices
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.
+Runtime power management (or runtime PM, sometimes shortened to RPM) allows
+individual I/O devices to transition between high and low-power states
+dynamically while the system is running, conserving power without waiting for a
+system-wide sleep state.
+
+Core Concepts
+-------------
+
+Understanding runtime PM requires distinguishing between several pairs of
+related but distinct concepts that apply to each device: **enabled** /
+**disabled**, **active** / **suspended**, and **allowed** / **forbidden**.
+
+* **Enabled**: To use runtime PM to manage a device's power states, it must
+ first be **enabled**. If RPM is never enabled for a device, it generally
+ stays inactive from an RPM perspective, and the PM core will ignore it.
+ If it is enabled, the PM core can manage the device status (see **Active**
+ below) according to its understanding of whether the device is in use, and
+ perform state transitions via the appropriate PM callbacks
+ (->runtime_suspend(), ->runtime_resume()).
+
+ Each device has an internal disable counter (``disable_depth``) which
+ determines whether runtime PM is currently enabled. Devices are initially
+ registered with runtime PM disabled (``disable_depth == 1``), though some bus
+ types (such as PCI) may enable it before driver probe.
+
+ To opt into runtime PM, a driver first ensures that the device's recorded
+ status matches its actual physical state (for example, by calling
+ pm_runtime_set_active() if the device was powered on at probe) and then calls
+ pm_runtime_enable(), decrementing ``disable_depth`` to zero (i.e.,
+ **enabled**). Runtime PM may be disabled again explicitly via
+ pm_runtime_disable() or temporarily during system sleep transitions.
+
+* **Active**: The PM core tracks a device's runtime status as either **active**
+ (the device is operational, having completed its resume callback or otherwise
+ marked active) or **suspended** (the device is idle or in a low-power state,
+ having completed its suspend callback or otherwise marked suspended), along
+ with transitional **suspending** and **resuming** phases. When runtime PM is
+ **enabled**, state transitions are primarily driven by reference counting:
+ drivers call pm_runtime_resume_and_get() (or related variants) before using
+ the hardware, to ensure the device is active; and pm_runtime_put() (or
+ related variants) once work completes. When a device's usage counter drops to
+ zero and its dependencies (children or consumers) are suspended, the PM core
+ can suspend the device immediately or after an autosuspend delay.
+
+ Besides driving the state of the device in question, a device's runtime
+ status also affects those of its dependencies — its parent (if the parent's
+ ``power.ignore_children`` is false) and its linked supplier device(s) (for
+ links with the ``DL_FLAG_PM_RUNTIME`` flag). An **active** device holds
+ reference counts on its dependencies, preventing them from suspending.
+
+* **Allowed**: System policy and user space govern whether dynamic suspension
+ is permitted through the concepts of **allowed** and **forbidden**,
+ manipulated in-kernel via pm_runtime_allow() and pm_runtime_forbid() and
+ exposed to user space through the ``/sys/devices/.../power/control``
+ attribute. When runtime PM is forbidden (``control`` set to ``on``), the PM
+ core increments the device's usage counter, forcing the device to remain
+ active regardless of whether the driver is idle. When runtime PM is allowed
+ (``control`` set to ``auto``), this reference is dropped, permitting the PM
+ core to automatically suspend the device whenever its driver and child
+ devices are no longer using it.
+
+Notably, runtime PM also has a feature called "autosuspend." This is different
+than the ``control`` notion of "auto" (i.e., "allowed"). Autosuspend is
+described in more detail in `Section 9`_.
+
+Implementation Structure
+------------------------
+
+Support for runtime power management is provided at the power management core
+(PM core) level by means of:
* Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
- include/linux/pm.h).
+ include/linux/pm.h). See `Section 2`_.
+
+* A number of runtime PM fields in the 'power' member of 'struct device' that
+ can be used for synchronizing runtime PM operations with one another. These
+ are covered in `Section 3`_.
* 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.
+ synchronization between them is taken care of by the PM core. Bus types and
+ device drivers are encouraged to use these functions. They are covered in
+ `Section 4`_.
-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.
+* 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.
.. _Section 2:
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 8/8] PM: runtime: Add Example Driver Patterns section
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (6 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
@ 2026-09-30 2:49 ` Brian Norris
2026-09-30 12:56 ` [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Rafael J. Wysocki (Intel)
8 siblings, 0 replies; 14+ messages in thread
From: Brian Norris @ 2026-09-30 2:49 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel, Brian Norris
The runtime PM API surface is pretty large, but there are a few common
patterns that many drivers should follow. Add some illustrative
examples, to help guide the most common audience for runtime PM docs --
driver writers.
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
Changes in v3:
* Rewrite Examples to avoid devm_* at first, to highlight correct
approaches
* Include error-handling and remove() in any probe() Examples
* Advise more caution when using devm_*, as ordering issues are subtle
Changes in v2:
* Add appropriate teardown to "Probe with Hardware Powered Off"
Example, as the remove() + power-off behavior is subtle here, and
easy to get wrong
Documentation/power/runtime_pm.rst | 475 ++++++++++++++++++++++++++++-
1 file changed, 473 insertions(+), 2 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index c63fbf0ff862..6eeb34ea2797 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -418,7 +418,8 @@ 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.
+detachment. See also the Examples in `Section 10`_ for some effective
+strategies for driver teardown.
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
@@ -643,7 +644,9 @@ 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::
+Here is a schematic pseudo-code example:
+
+.. code-block:: c
foo_read_or_write(struct foo_priv *foo, void *data)
{
@@ -709,3 +712,471 @@ 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.
+
+.. _Section 10:
+
+10. Example Driver Patterns
+===========================
+
+The runtime PM API is large and complex, but most device drivers follow a small
+set of canonical patterns when interacting with runtime PM. This section
+illustrates standard patterns for device probing, performing I/O, and handling
+interrupts.
+
+Probe and Initialization
+------------------------
+
+Basic Probe
+~~~~~~~~~~~
+
+A driver that powers on its hardware during probe and does not use autosuspend
+can initialize runtime PM using standard helpers:
+
+.. code-block:: c
+
+ static int foo_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct foo_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ /* Power on and initialize hardware registers... */
+
+ /*
+ * The code above left hardware powered on and operational, so
+ * tell the PM core that the device is active before enabling
+ * runtime PM.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ /*
+ * Perform remaining driver setup (e.g. register interrupts, device nodes).
+ * If any step fails after enabling runtime PM:
+ */
+ ret = foo_register_device(priv);
+ if (ret)
+ goto err_pm_disable;
+
+ /*
+ * Upon successful return from ->probe(), the driver core
+ * automatically executes pm_request_idle(dev), allowing the
+ * device to suspend asynchronously if its usage counter is zero.
+ */
+ return 0;
+
+ err_pm_disable:
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev)) {
+ /*
+ * Power back off, in case device did not suspend yet.
+ * For example, leverage your .runtime_suspend()
+ * implementation:
+ */
+ foo_runtime_suspend(dev);
+ pm_runtime_set_suspended(dev);
+ }
+ return ret;
+ }
+
+ static void foo_remove(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct foo_priv *priv = platform_get_drvdata(pdev);
+
+ foo_unregister_device(priv);
+
+ pm_runtime_disable(dev);
+ /*
+ * The runtime PM status is not guaranteed at this point. We
+ * could be either suspended or active, so we need to handle
+ * both.
+ */
+ if (!pm_runtime_status_suspended(dev)) {
+ /* Power back off, in case device did not suspend yet. */
+ foo_runtime_suspend(dev);
+ pm_runtime_set_suspended(dev);
+ }
+ }
+
+Drivers using this pattern should ensure that hardware is powered off cleanly
+upon driver unbind or probe error. If the device was still active when detached
+(for example, if user space configured ``/sys/devices/.../power/control`` to
+``on``, or if the device has not yet idled), ``foo_remove()`` and
+``err_pm_disable`` disable runtime PM, check whether the device is not yet
+suspended using pm_runtime_status_suspended(), and manually power the device
+back off.
+
+Note that device-managed helpers such as devm_pm_runtime_enable() and
+devm_pm_runtime_set_active_enabled() exist, but they only call
+pm_runtime_disable() upon driver unbind; they do not take care of device
+quiesce and power-off. See the `Autosuspend and Device-Managed Probe`_ section
+below for how to encapsulate complete teardown in a custom devm action.
+
+Probe with Hardware Powered Off
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many drivers prefer to keep hardware powered off or in low power until
+actually needed, avoiding duplicate power sequencing logic between ->probe()
+and ->runtime_resume(). Because the initial runtime PM state of a device is
+suspended by default, the driver can enable runtime PM directly and rely on
+pm_runtime_resume_and_get() to trigger the ->runtime_resume() callback when
+probe needs to access hardware:
+
+.. code-block:: c
+
+ static int foo_runtime_suspend(struct device *dev)
+ {
+ struct foo_priv *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->clk);
+ regulator_disable(priv->supply);
+
+ return 0;
+ }
+
+ static int foo_runtime_resume(struct device *dev)
+ {
+ struct foo_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_enable(priv->supply);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ regulator_disable(priv->supply);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ static int foo_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct foo_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ /* Acquire regulators, clocks, GPIOs, and register map... */
+
+ /*
+ * Hardware starts powered off. The default state is
+ * RPM_SUSPENDED, so no need for:
+ * pm_runtime_set_suspended(dev);
+ */
+
+ pm_runtime_enable(dev);
+
+ /*
+ * Power on the device via ->runtime_resume() to verify device
+ * ID or perform initial hardware configuration.
+ */
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ ret = foo_verify_hardware_id(priv);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ goto err_pm_disable;
+ }
+
+ /*
+ * Drop the usage counter, allowing ->runtime_suspend() to
+ * power off the device until an I/O request arrives.
+ */
+ pm_runtime_put(dev);
+
+ return 0;
+
+ err_pm_disable:
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev)) {
+ foo_runtime_suspend(dev);
+ pm_runtime_set_suspended(dev);
+ }
+ return ret;
+ }
+
+ static void foo_remove(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev)) {
+ foo_runtime_suspend(dev);
+ pm_runtime_set_suspended(dev);
+ }
+ }
+
+Note that this pattern requires ``CONFIG_PM``. When ``CONFIG_PM`` is
+disabled, pm_runtime_resume_and_get() returns 0 without calling
+->runtime_resume(), leaving hardware unpowered. Drivers using this pattern
+should typically depend on ``CONFIG_PM``.
+
+Similar to the Basic Probe example, drivers using this pattern also must
+exercise care when handling probe() errors or performing unbind/remove(), to
+ensure they power off and clean up resources that they manage with runtime
+suspend/resume. Typically, this may mean explicitly powering off if not already
+suspended.
+
+Autosuspend and Device-Managed Probe
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the driver uses autosuspend, it configures the autosuspend delay and enables
+autosuspend before enabling runtime PM.
+
+Additionally, drivers can use device-managed (``devm_*``) helpers to clean up
+resources on probe failure or driver unbind. This provides an alternative to
+writing complicated ``goto``-based error paths, with similar teardown code in
+remove(). Note that drivers must still exercise care to avoid assuming a
+particular runtime PM status in these cases; a device typically may be either
+**active** or **suspended**, and so ``devm``-based teardown code must be
+written accordingly.
+
+.. code-block:: c
+
+ /* Tear-down action, for error handling or driver unbind. */
+ static void foo_poweroff_action(void *data)
+ {
+ struct device *dev = data;
+
+ /* Runtime PM is already disabled by this point. */
+
+ if (!pm_runtime_status_suspended(dev)) {
+ /*
+ * Power device back off, in case device was left active.
+ * e.g., leverage .runtime_suspend() routine:
+ */
+ foo_runtime_suspend(dev);
+
+ pm_runtime_set_suspended(dev);
+ }
+ }
+
+ static int foo_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct foo_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ /* Power on and initialize hardware registers... */
+
+ pm_runtime_set_active(dev);
+
+ /*
+ * Guarantee hardware is powered off upon unbind or probe error.
+ * Register this action before devm_pm_runtime_enable() to
+ * ensure runtime PM status is frozen by the time we tear down
+ * here.
+ */
+ ret = devm_add_action_or_reset(dev, foo_poweroff_action, dev);
+ if (ret)
+ return ret;
+
+ /* Set autosuspend delay (e.g., 2000 ms) and enable autosuspend. */
+ pm_runtime_set_autosuspend_delay(dev, 2000);
+ pm_runtime_use_autosuspend(dev);
+
+ /*
+ * Update last busy timestamp so the driver core's post-probe
+ * pm_request_idle() respects the autosuspend delay.
+ */
+ pm_runtime_mark_last_busy(dev);
+
+ /*
+ * devm_pm_runtime_enable() ensures that pm_runtime_disable()
+ * and pm_runtime_dont_use_autosuspend() are called upon driver
+ * unbind.
+ */
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+ }
+
+Key points:
+
+* **Guaranteed Power-off on Detach**: Again similar to the Basic Probe example,
+ we must exercise care in case the device was still active during probe
+ failure or driver unbind. In this case, we encapsulate the teardown using
+ device-managed actions.
+* **LIFO Teardown Ordering**: Because devm releases resources in reverse
+ order of registration (LIFO), registering foo_poweroff_action() before
+ devm_pm_runtime_enable() ensures that runtime PM is disabled first, and the
+ device is suspended *before* devm disables any clocks or regulators
+ acquired earlier in ->probe().
+* **Omission of ->remove()**: If all other resources in the driver are managed
+ with ``devm`` helpers, this eliminates both manual ``goto``-based unwinding
+ in ->probe() and the need for an explicit ->remove() callback.
+
+Performing I/O Operations
+-------------------------
+
+Before accessing hardware registers or initiating I/O transfers, drivers must
+ensure the device is active by calling pm_runtime_resume_and_get() or similar.
+
+Basic I/O
+~~~~~~~~~
+
+For devices without autosuspend, work completion is signaled with
+pm_runtime_put(), which drops the usage counter and queues an asynchronous idle
+check once the counter reaches zero:
+
+.. code-block:: c
+
+ int foo_do_transfer(struct foo_priv *priv, void *buf, size_t count)
+ {
+ int ret;
+
+ ret = pm_runtime_resume_and_get(priv->dev);
+ if (ret < 0)
+ return ret;
+
+ /* Access hardware registers or perform data transfer... */
+ ret = foo_hardware_transfer(priv, buf, count);
+
+ /*
+ * Drop usage counter and request asynchronous idle check (and
+ * suspend, if possible).
+ */
+ pm_runtime_put(priv->dev);
+
+ return ret;
+ }
+
+Autosuspend I/O
+~~~~~~~~~~~~~~~
+
+For devices using autosuspend, work completion is signaled with
+pm_runtime_put_autosuspend(), which drops the usage counter and defers
+suspension until the autosuspend delay expires:
+
+.. code-block:: c
+
+ int foo_do_transfer(struct foo_priv *priv, void *buf, size_t count)
+ {
+ int ret;
+
+ ret = pm_runtime_resume_and_get(priv->dev);
+ if (ret < 0)
+ return ret;
+
+ /* Access hardware registers or perform data transfer... */
+ ret = foo_hardware_transfer(priv, buf, count);
+
+ /*
+ * Drop the usage counter and schedule an autosuspend once
+ * the delay expires. Note that pm_runtime_put_autosuspend()
+ * updates the last-access timestamp automatically.
+ */
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
+ }
+
+Synchronous Completion
+~~~~~~~~~~~~~~~~~~~~~~
+
+When immediate suspension is desired -- such as before unregistering a
+device or during shutdown -- synchronous put helpers can be used instead of
+their asynchronous counterparts. Which helper to use depends on whether
+autosuspend is configured:
+
+* For non-autosuspend devices, use pm_runtime_put_sync().
+* For devices that use autosuspend, use pm_runtime_put_sync_suspend(), which
+ ignores any configured autosuspend delay and forces immediate suspension.
+
+However, note several important caveats when relying on synchronous runtime
+PM helpers for power-down:
+
+* **Parents and Suppliers**: While the target device itself is suspended
+ synchronously, the PM core handles idle notifications for parents and
+ device link suppliers asynchronously. As a result, parent devices or
+ power domain suppliers are not guaranteed to be powered off when the
+ function returns.
+* **User Policy ("Forbidden")**: Runtime PM helpers respect system policy.
+ If user space has set ``/sys/devices/.../power/control`` to ``on``
+ (pm_runtime_forbid()), the PM core holds an extra reference on the
+ device, meaning dropping the driver's usage counter will not trigger a
+ suspend.
+
+Because of these constraints, synchronous put helpers may not be suitable
+when a driver functionally requires hardware to be powered off
+synchronously (for example, to perform a hardware reset or power cycle).
+Such requirements may necessitate other methods, such as disabling runtime
+PM with pm_runtime_disable() and explicitly executing the hardware
+power-down sequence.
+
+Interrupt Handling with Conditional Get
+---------------------------------------
+
+Interrupt handlers (especially in atomic or hardirq context) cannot typically
+invoke pm_runtime_resume_and_get(), because runtime-resume may sleep. Moreover,
+if an interrupt arrives while the device is suspended or transitioning to low
+power (e.g., on a shared interrupt line or spurious wakeups), attempting to
+read hardware registers could trigger a bus fault or system hang.
+
+To handle this safely, drivers can conditionally acquire a runtime PM reference
+using pm_runtime_get_if_in_use() or pm_runtime_get_if_active():
+
+.. code-block:: c
+
+ static irqreturn_t foo_irq_handler(int irq, void *dev_id)
+ {
+ struct foo_priv *priv = dev_id;
+ irqreturn_t ret = IRQ_NONE;
+
+ /*
+ * Check if the device is active before reading hardware
+ * registers. If the device is suspended, this interrupt
+ * cannot belong to us (or was already serviced).
+ *
+ * Note that this also will drop interrupts while runtime PM is
+ * disabled.
+ */
+ if (pm_runtime_get_if_active(priv->dev) <= 0)
+ return IRQ_NONE;
+
+ /* Hardware is active and usage count is incremented */
+ if (foo_has_pending_irq(priv)) {
+ foo_service_irq(priv);
+ ret = IRQ_HANDLED;
+ }
+
+ /*
+ * Release the reference acquired by pm_runtime_get_if_active().
+ * For autosuspend devices, use pm_runtime_put_autosuspend();
+ * for non-autosuspend devices, use pm_runtime_put().
+ */
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
+ }
+
+Both pm_runtime_get_if_in_use() and pm_runtime_get_if_active() are safe to use
+from an interrupt routine. One example where a device might be active but not
+"in use" is if autosuspend is used. A device will stay active for a while with
+no users. If interrupts should still be serviced for a device in this state,
+pm_runtime_get_if_active() should be used.
--
2.56.0.rc1.315.gc6ed9934b7-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (7 preceding siblings ...)
2026-09-30 2:49 ` [PATCH v3 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
@ 2026-09-30 12:56 ` Rafael J. Wysocki (Intel)
8 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-09-30 12:56 UTC (permalink / raw)
To: Brian Norris
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
linux-kernel
On Wed, Sep 30, 2026 at 4:51 AM Brian Norris <briannorris@chromium.org> wrote:
>
> The runtime PM documentation could use some improvements and additions,
> to help guide people less familiar with the main runtime PM concepts and
> its internal implementation details.
>
> v1 is here:
> https://lore.kernel.org/all/20260904212000.4167880-1-briannorris@chromium.org/
>
> v2 is here:
> https://lore.kernel.org/all/20260923174711.1283986-1-briannorris@chromium.org/
>
> The first part of the v1 series has already been applied. For the
> remaining work:
>
> - Formatting and clarity improvements.
>
> - Clarifying core concepts in the Introduction. (Pretty much all new
> readers I encounter have a hard time with the difference between
> "enabled", "allowed", and "active".)
>
> - Adding Example driver patterns -- because the API is so large and
> complicated, it can help to try to walk people through standard
> practices, and what everything means in context.
>
> I tried to keep some of the larger changes toward the end, to hopefully
> make it easier to rework or reject them while cherry-picking some of the
> easier stuff from the first part of the series.
>
> Feel free to add suggestions! Within reason, I'm open to tackling more
> here, as I think many people have many valid perspectives on exactly why
> and how the docs do or don't serve people well today. Or I can tackle
> less, if you think some of my choices are not improvements.
>
> Some possible follow-ups I'm toying with:
>
> * Slimming down the API might be better than heavily documenting it. A
> smaller API is a more digestible API.
>
> My only concrete next step: drop __pm_runtime_put_autosuspend(). Its
> last user is nearly gone:
> https://lore.kernel.org/all/20260806-smmu-rpm-v4-1-8183d007331c@oss.qualcomm.com/
>
> I could also see deprecating one of
> pm_runtime_put_sync{,_suspend,_autosuspend}(). They all do slightly
> different things, but I'm not sure every difference is actually fully
> intentional (or at least, not necessary).
>
> * Tweaking some of the behavior on pm_runtime_barrier(). Today, it's
> very asymmetric, as it prefers resume. But I believe there may be
> value in making it flush (not just cancel) pending suspend too. That
> may be in a future proposal; for now, I just try to make its
> asymmetry more clear in the docs.
>
> * Sand down some more rough edges on return codes. For example, it's
> very difficult to get any useful meaning out of pm_runtime_put_sync()
> return codes. There's a high chance that anyone trying to treat
> return codes as errors is inviting bugs. (Is -EAGAIN a failure?)
>
> Of course, the answer there is not "document it better" -- we can
> make it easier to use.
>
> * Adjust the way devm_pm_runtime_enable() works, specifically for
> remove()/teardown. Currently, this is very hard to use correctly --
> some common driver patterns may assume that a device will tear down
> while RPM_SUSPENDED; but that's not actually guaranteed. Notably,
> this makes some of the "Examples" section fairly tricky/subtle.
>
> Regards,
> Brian
>
> Changes in v3:
> * Misc formatting improvements
> * Rewrite Examples to avoid devm_* at first, to highlight correct
> approaches
> * Include error-handling and remove() in any probe() Examples
> * Advise more caution when using devm_*, as ordering issues are subtle
>
> Changes in v2:
> * Major rework on Introduction section, especially regarding "enabled"
> and "active"
> * Add appropriate teardown to "Probe with Hardware Powered Off"
> Example, as the remove() + power-off behavior is subtle here, and
> easy to get wrong
> * Drop changes that are already applied
> * Add a few new fix patches, noticed while reviewing the rest
> * Move Introduction patch near the end of the series, as it is a likely
> target for further discussion and modification.
> * Correct Ulf's email address
> * CC linux-doc
>
> Brian Norris (8):
> PM: runtime: Correct pm_runtime_autosuspend_expiration() doc
> PM: runtime: More kerneldoc formatting
> PM: runtime: Misc improvements to runtime_pm.rst
> PM: runtime: Add "Section" hyperlinks
> PM: runtime: Clarify ->runtime_idle() callback return value handling
> PM: runtime: Clarify driver callback expectations and structure
> Section 2
> PM: runtime: Expand introduction with core concepts and structure
> PM: runtime: Add Example Driver Patterns section
Patches [1-6/8] are fine with me now, so applied (as 7.4 material).
I will send comments on patch [7/8] separately and the last one is
still under review.
Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-30 2:49 ` [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
@ 2026-09-30 15:41 ` Rafael J. Wysocki (Intel)
2026-09-30 23:40 ` Brian Norris
2026-09-30 15:44 ` Ulf Hansson
1 sibling, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-09-30 15:41 UTC (permalink / raw)
To: Brian Norris
Cc: Rafael J . Wysocki, Pavel Machek, Doug Anderson, Ulf Hansson,
linux-doc, linux-pm, Len Brown, linux-kernel
On Wed, Sep 30, 2026 at 4:51 AM Brian Norris <briannorris@chromium.org> wrote:
>
> I commonly see people have difficulty learning how runtime PM works
> because of the following key points [*]:
>
> 1) there are several boolean concepts in runtime PM, with somewhat
> similar meanings:
>
> enabled / disabled
> active / suspended
> allowed / forbidden
>
> 2) if these concepts are documented at all, they're scattered across
> the kerneldoc or Documentation/
>
> 3) the runtime_pm.rst docs don't make any attempt to ease a reader into
> understanding the concepts, and instead jump straight into how it's
> implemented (queues, 'struct device' fields, helpers).
>
> Let's try to remedy this a bit by discussing the core concepts and
> highlights at the top of the introduction, and introduce a few
> sub-headings, so it's easier to navigate different aspects of the
> introduction.
>
> While shuffling the intro around, I also see that the existing text
> largely mirrors the layout of the following sections (2, 3, and 4), but
> does so out of order. Reorder those, and point to section numbers.
>
> [*] In addition to API complexity. I count 61 pm_*() helpers, 7 of which
> are variations of put() and 8 of which are variations of get().
>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
>
> (no changes since v2)
>
> Changes in v2:
> Address review feedback around descriptions of "enabled" and "active". I
> know not every point of discussion was settled, but I hope this updated
> version resolves many of them and provides a better basis for further
> improvement.
> * Avoid calling enabled and active "orthogonal"
> * Describe more of their inter-relationship
> * Prioritize talking about "enabled" first, since that's the first
> concept a reader should know about
> * Brief mentions of parent/child and supplier/consumer, and dependency
> handling
> * Other tweaks
>
> Documentation/power/runtime_pm.rst | 103 +++++++++++++++++++++++------
> 1 file changed, 84 insertions(+), 19 deletions(-)
>
> diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> index 68903d93a3e7..c63fbf0ff862 100644
> --- a/Documentation/power/runtime_pm.rst
> +++ b/Documentation/power/runtime_pm.rst
> @@ -13,31 +13,96 @@ Runtime Power Management Framework for I/O Devices
> 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.
> +Runtime power management (or runtime PM, sometimes shortened to RPM) allows
> +individual I/O devices to transition between high and low-power states
> +dynamically while the system is running, conserving power without waiting for a
> +system-wide sleep state.
I would rephrase the above as follows:
"Runtime power management (or runtime PM, sometimes also referred to
as RPM) allows individual I/O devices that are not in active use to be
put into low-power states, in which they may not be operational or
even accessible, and go back to the fully operational state as needed.
Power can be reduced this way without waiting for a transition into a
system-wide sleep state."
> +
> +Core Concepts
> +-------------
> +
> +Understanding runtime PM requires distinguishing between several pairs of
> +related but distinct concepts that apply to each device: **enabled** /
> +**disabled**, **active** / **suspended**, and **allowed** / **forbidden**.
> +
> +* **Enabled**: To use runtime PM to manage a device's power states, it must
> + first be **enabled**. If RPM is never enabled for a device, it generally
> + stays inactive from an RPM perspective, and the PM core will ignore it.
> + If it is enabled, the PM core can manage the device status (see **Active**
> + below) according to its understanding of whether the device is in use, and
> + perform state transitions via the appropriate PM callbacks
> + (->runtime_suspend(), ->runtime_resume()).
> +
> + Each device has an internal disable counter (``disable_depth``) which
> + determines whether runtime PM is currently enabled. Devices are initially
> + registered with runtime PM disabled (``disable_depth == 1``), though some bus
> + types (such as PCI) may enable it before driver probe.
> +
> + To opt into runtime PM, a driver first ensures that the device's recorded
> + status matches its actual physical state (for example, by calling
> + pm_runtime_set_active() if the device was powered on at probe) and then calls
> + pm_runtime_enable(), decrementing ``disable_depth`` to zero (i.e.,
> + **enabled**). Runtime PM may be disabled again explicitly via
> + pm_runtime_disable() or temporarily during system sleep transitions.
> +
> +* **Active**: The PM core tracks a device's runtime status as either **active**
> + (the device is operational, having completed its resume callback or otherwise
> + marked active) or **suspended** (the device is idle or in a low-power state,
> + having completed its suspend callback or otherwise marked suspended), along
> + with transitional **suspending** and **resuming** phases. When runtime PM is
> + **enabled**, state transitions are primarily driven by reference counting:
> + drivers call pm_runtime_resume_and_get() (or related variants) before using
> + the hardware, to ensure the device is active; and pm_runtime_put() (or
> + related variants) once work completes. When a device's usage counter drops to
> + zero and its dependencies (children or consumers) are suspended, the PM core
> + can suspend the device immediately or after an autosuspend delay.
> +
> + Besides driving the state of the device in question, a device's runtime
> + status also affects those of its dependencies — its parent (if the parent's
> + ``power.ignore_children`` is false) and its linked supplier device(s) (for
> + links with the ``DL_FLAG_PM_RUNTIME`` flag). An **active** device holds
> + reference counts on its dependencies, preventing them from suspending.
> +
> +* **Allowed**: System policy and user space govern whether dynamic suspension
> + is permitted through the concepts of **allowed** and **forbidden**,
> + manipulated in-kernel via pm_runtime_allow() and pm_runtime_forbid() and
> + exposed to user space through the ``/sys/devices/.../power/control``
> + attribute. When runtime PM is forbidden (``control`` set to ``on``), the PM
> + core increments the device's usage counter, forcing the device to remain
> + active regardless of whether the driver is idle. When runtime PM is allowed
> + (``control`` set to ``auto``), this reference is dropped, permitting the PM
> + core to automatically suspend the device whenever its driver and child
> + devices are no longer using it.
> +
> +Notably, runtime PM also has a feature called "autosuspend." This is different
> +than the ``control`` notion of "auto" (i.e., "allowed"). Autosuspend is
> +described in more detail in `Section 9`_.
Regarding the above, I have reconsidered it with the conclusion that
it would be better to describe "active" and "suspended" first and
"enabled" and "disabled" subsequently, and maybe without going too
much into details yet. Here's my version of it:
"There are some device-level concepts that need to be grasped in order
to understand runtime PM as a whole.
First of all, runtime PM tracks whether or not devices are in active
use, which generally means that they are accessible and operational,
and may be depended on by something (for example, other devices or
user space). That is represented by the **active** meta-state of a
device from the runtime PM perspective. The other persistent device
meta-state used by runtime PM, called **suspended**, represents a
promise that the given device will not be accessed. This covers
devices in low-power states, but it also may include devices that are
not fully operational, or are regarded as such, for other reasons.
There are also two transient meta-states, **suspending** and
**resuming**, that represent transitions between **active** and
**suspended** often referred to as *runtime suspend* and *runtime
resume*, or just *suspend* and *resume*, respectively. Every device
handled by runtime PM is in one of these four meta-states at any time
and the meta-state it is in is expected to reflect its actual physical
configuration (that is, for instance, if the device is not accessible,
it cannot be **active**). The term "runtime PM state" used in what
follows refers to the meta-states described above.
Second, in order to track the runtime PM state and carry out
transitions between **active** and **suspended**, runtime PM needs to
be **enabled** for the given device. If it is **disabled**, it
generally leaves the device alone. This means in particular that the
runtime PM state of a device and its actual physical configuration may
get out of sync after disabling runtime PM for it. Analogously, the
runtime PM state of a device may need to be explicitly adjusted to
reflect its current physical configuration before enabling runtime PM
for it. Moreover, it is generally not recommended to leave devices in
the **active** meta-state after disabling runtime PM for them because
that may affect what can be done to their ancestors and suppliers
going forward.
More specifically, in addition to tracking the runtime PM state of
every device, runtime PM tracks dependencies between different
devices. In fact, that dependency tracking mechanism is the main
reason for using runtime PM. The idea is that in order for a device
to become **active**, all of the devices it depends on must also be
**active** and that is enforced by runtime PM. Accordingly, an
attempt to resume a device causes all of the devices it depends on to
become **active** and remain **active** until the given device is
suspended. In turn, an attempt to suspend a device may allow the
devices it depends on to also suspend unless they are additionally
depended on by something else. While desirable so long as runtime PM
is **enabled**, this may become problematic when runtime PM is
**disabled** because the tracking of dependencies does not stop
automatically at that point and it may cause some devices to remain
**active** unnecessarily.
As a rule, runtime PM is **disabled** for all devices to start with,
but there are bus types that enable it for every device (for instance,
the PCI bus type does so). Generally speaking, drivers are expected
to know which bus they belong to and so they should also know whether
or not runtime PM has been enabled for the devices handled by them
already. In the cases in which runtime PM is not enabled by the bus
type, drivers are responsible for enabling it if they want to
participate in it. The devices for which runtime PM has never been
enabled are black boxes from its point of view.
Finally, runtime PM may be **forbidden** even though it has been
enabled. Doing so causes the given device to transition into the
**active** meta-state (unless it has been **active** already before)
and prevents it from being suspended. In other words, a device with
forbidden runtime PM remains **active** at least until runtime PM is
**allowed** for it again. This mechanism is not only available to
kernel code, but it may also be used by user space through the
``/sys/devices/.../power/control`` *sysfs* attribute of the given
device. Namely, writing ``on`` to that attribute causes runtime PM to
be forbidden for it, and writing ``auto`` to that attribute causes
runtime PM to be allowed. User space may use that attribute at any
time, so the ability to transition a device into the **suspended**
meta-state via runtime PM must not be relied on for correctness, among
other things."
I think that it provides all of the information needed to start with
without pulling too much stuff documented elsewhere.
If you agree with the above, I'll send my version as a separate patch.
> +
> +Implementation Structure
> +------------------------
> +
> +Support for runtime power management is provided at the power management core
> +(PM core) level by means of:
>
> * Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
> - include/linux/pm.h).
> + include/linux/pm.h). See `Section 2`_.
> +
> +* A number of runtime PM fields in the 'power' member of 'struct device' that
> + can be used for synchronizing runtime PM operations with one another. These
> + are covered in `Section 3`_.
>
> * 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.
> + synchronization between them is taken care of by the PM core. Bus types and
> + device drivers are encouraged to use these functions. They are covered in
> + `Section 4`_.
>
> -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.
> +* 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.
>
> .. _Section 2:
>
> --
The last part above looks fine to me.
Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-30 2:49 ` [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
2026-09-30 15:41 ` Rafael J. Wysocki (Intel)
@ 2026-09-30 15:44 ` Ulf Hansson
1 sibling, 0 replies; 14+ messages in thread
From: Ulf Hansson @ 2026-09-30 15:44 UTC (permalink / raw)
To: Brian Norris
Cc: Rafael J . Wysocki, Pavel Machek, Doug Anderson, Ulf Hansson,
linux-doc, linux-pm, Len Brown, linux-kernel
On Wed, Sep 30, 2026 at 4:51 AM Brian Norris <briannorris@chromium.org> wrote:
>
> I commonly see people have difficulty learning how runtime PM works
> because of the following key points [*]:
>
> 1) there are several boolean concepts in runtime PM, with somewhat
> similar meanings:
>
> enabled / disabled
> active / suspended
> allowed / forbidden
>
> 2) if these concepts are documented at all, they're scattered across
> the kerneldoc or Documentation/
>
> 3) the runtime_pm.rst docs don't make any attempt to ease a reader into
> understanding the concepts, and instead jump straight into how it's
> implemented (queues, 'struct device' fields, helpers).
>
> Let's try to remedy this a bit by discussing the core concepts and
> highlights at the top of the introduction, and introduce a few
> sub-headings, so it's easier to navigate different aspects of the
> introduction.
>
> While shuffling the intro around, I also see that the existing text
> largely mirrors the layout of the following sections (2, 3, and 4), but
> does so out of order. Reorder those, and point to section numbers.
>
> [*] In addition to API complexity. I count 61 pm_*() helpers, 7 of which
> are variations of put() and 8 of which are variations of get().
>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
I guess Rafael may have some further comment on this one, but from my
point of view this looks fine. Please add:
Reviewed-by: Ulf Hansson <ulfh@kernel.org>
Kind regards
Uffe
> ---
>
> (no changes since v2)
>
> Changes in v2:
> Address review feedback around descriptions of "enabled" and "active". I
> know not every point of discussion was settled, but I hope this updated
> version resolves many of them and provides a better basis for further
> improvement.
> * Avoid calling enabled and active "orthogonal"
> * Describe more of their inter-relationship
> * Prioritize talking about "enabled" first, since that's the first
> concept a reader should know about
> * Brief mentions of parent/child and supplier/consumer, and dependency
> handling
> * Other tweaks
>
> Documentation/power/runtime_pm.rst | 103 +++++++++++++++++++++++------
> 1 file changed, 84 insertions(+), 19 deletions(-)
>
> diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> index 68903d93a3e7..c63fbf0ff862 100644
> --- a/Documentation/power/runtime_pm.rst
> +++ b/Documentation/power/runtime_pm.rst
> @@ -13,31 +13,96 @@ Runtime Power Management Framework for I/O Devices
> 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.
> +Runtime power management (or runtime PM, sometimes shortened to RPM) allows
> +individual I/O devices to transition between high and low-power states
> +dynamically while the system is running, conserving power without waiting for a
> +system-wide sleep state.
> +
> +Core Concepts
> +-------------
> +
> +Understanding runtime PM requires distinguishing between several pairs of
> +related but distinct concepts that apply to each device: **enabled** /
> +**disabled**, **active** / **suspended**, and **allowed** / **forbidden**.
> +
> +* **Enabled**: To use runtime PM to manage a device's power states, it must
> + first be **enabled**. If RPM is never enabled for a device, it generally
> + stays inactive from an RPM perspective, and the PM core will ignore it.
> + If it is enabled, the PM core can manage the device status (see **Active**
> + below) according to its understanding of whether the device is in use, and
> + perform state transitions via the appropriate PM callbacks
> + (->runtime_suspend(), ->runtime_resume()).
> +
> + Each device has an internal disable counter (``disable_depth``) which
> + determines whether runtime PM is currently enabled. Devices are initially
> + registered with runtime PM disabled (``disable_depth == 1``), though some bus
> + types (such as PCI) may enable it before driver probe.
> +
> + To opt into runtime PM, a driver first ensures that the device's recorded
> + status matches its actual physical state (for example, by calling
> + pm_runtime_set_active() if the device was powered on at probe) and then calls
> + pm_runtime_enable(), decrementing ``disable_depth`` to zero (i.e.,
> + **enabled**). Runtime PM may be disabled again explicitly via
> + pm_runtime_disable() or temporarily during system sleep transitions.
> +
> +* **Active**: The PM core tracks a device's runtime status as either **active**
> + (the device is operational, having completed its resume callback or otherwise
> + marked active) or **suspended** (the device is idle or in a low-power state,
> + having completed its suspend callback or otherwise marked suspended), along
> + with transitional **suspending** and **resuming** phases. When runtime PM is
> + **enabled**, state transitions are primarily driven by reference counting:
> + drivers call pm_runtime_resume_and_get() (or related variants) before using
> + the hardware, to ensure the device is active; and pm_runtime_put() (or
> + related variants) once work completes. When a device's usage counter drops to
> + zero and its dependencies (children or consumers) are suspended, the PM core
> + can suspend the device immediately or after an autosuspend delay.
> +
> + Besides driving the state of the device in question, a device's runtime
> + status also affects those of its dependencies — its parent (if the parent's
> + ``power.ignore_children`` is false) and its linked supplier device(s) (for
> + links with the ``DL_FLAG_PM_RUNTIME`` flag). An **active** device holds
> + reference counts on its dependencies, preventing them from suspending.
> +
> +* **Allowed**: System policy and user space govern whether dynamic suspension
> + is permitted through the concepts of **allowed** and **forbidden**,
> + manipulated in-kernel via pm_runtime_allow() and pm_runtime_forbid() and
> + exposed to user space through the ``/sys/devices/.../power/control``
> + attribute. When runtime PM is forbidden (``control`` set to ``on``), the PM
> + core increments the device's usage counter, forcing the device to remain
> + active regardless of whether the driver is idle. When runtime PM is allowed
> + (``control`` set to ``auto``), this reference is dropped, permitting the PM
> + core to automatically suspend the device whenever its driver and child
> + devices are no longer using it.
> +
> +Notably, runtime PM also has a feature called "autosuspend." This is different
> +than the ``control`` notion of "auto" (i.e., "allowed"). Autosuspend is
> +described in more detail in `Section 9`_.
> +
> +Implementation Structure
> +------------------------
> +
> +Support for runtime power management is provided at the power management core
> +(PM core) level by means of:
>
> * Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
> - include/linux/pm.h).
> + include/linux/pm.h). See `Section 2`_.
> +
> +* A number of runtime PM fields in the 'power' member of 'struct device' that
> + can be used for synchronizing runtime PM operations with one another. These
> + are covered in `Section 3`_.
>
> * 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.
> + synchronization between them is taken care of by the PM core. Bus types and
> + device drivers are encouraged to use these functions. They are covered in
> + `Section 4`_.
>
> -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.
> +* 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.
>
> .. _Section 2:
>
> --
> 2.56.0.rc1.315.gc6ed9934b7-goog
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-30 15:41 ` Rafael J. Wysocki (Intel)
@ 2026-09-30 23:40 ` Brian Norris
2026-10-01 12:59 ` Rafael J. Wysocki (Intel)
0 siblings, 1 reply; 14+ messages in thread
From: Brian Norris @ 2026-09-30 23:40 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel)
Cc: Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel
Hi Rafael,
On Wed, Sep 30, 2026 at 05:41:56PM +0200, Rafael J. Wysocki (Intel) wrote:
> On Wed, Sep 30, 2026 at 4:51 AM Brian Norris <briannorris@chromium.org> wrote:
> >
> > I commonly see people have difficulty learning how runtime PM works
> > because of the following key points [*]:
> >
> > 1) there are several boolean concepts in runtime PM, with somewhat
> > similar meanings:
> >
> > enabled / disabled
> > active / suspended
> > allowed / forbidden
> >
> > 2) if these concepts are documented at all, they're scattered across
> > the kerneldoc or Documentation/
> >
> > 3) the runtime_pm.rst docs don't make any attempt to ease a reader into
> > understanding the concepts, and instead jump straight into how it's
> > implemented (queues, 'struct device' fields, helpers).
> >
> > Let's try to remedy this a bit by discussing the core concepts and
> > highlights at the top of the introduction, and introduce a few
> > sub-headings, so it's easier to navigate different aspects of the
> > introduction.
> >
> > While shuffling the intro around, I also see that the existing text
> > largely mirrors the layout of the following sections (2, 3, and 4), but
> > does so out of order. Reorder those, and point to section numbers.
> >
> > [*] In addition to API complexity. I count 61 pm_*() helpers, 7 of which
> > are variations of put() and 8 of which are variations of get().
> >
> > Signed-off-by: Brian Norris <briannorris@chromium.org>
> > ---
> >
> > (no changes since v2)
> >
> > Changes in v2:
> > Address review feedback around descriptions of "enabled" and "active". I
> > know not every point of discussion was settled, but I hope this updated
> > version resolves many of them and provides a better basis for further
> > improvement.
> > * Avoid calling enabled and active "orthogonal"
> > * Describe more of their inter-relationship
> > * Prioritize talking about "enabled" first, since that's the first
> > concept a reader should know about
> > * Brief mentions of parent/child and supplier/consumer, and dependency
> > handling
> > * Other tweaks
> >
> > Documentation/power/runtime_pm.rst | 103 +++++++++++++++++++++++------
> > 1 file changed, 84 insertions(+), 19 deletions(-)
> >
> > diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> > index 68903d93a3e7..c63fbf0ff862 100644
> > --- a/Documentation/power/runtime_pm.rst
> > +++ b/Documentation/power/runtime_pm.rst
> > @@ -13,31 +13,96 @@ Runtime Power Management Framework for I/O Devices
> > 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.
> > +Runtime power management (or runtime PM, sometimes shortened to RPM) allows
> > +individual I/O devices to transition between high and low-power states
> > +dynamically while the system is running, conserving power without waiting for a
> > +system-wide sleep state.
>
> I would rephrase the above as follows:
>
> "Runtime power management (or runtime PM, sometimes also referred to
> as RPM) allows individual I/O devices that are not in active use to be
> put into low-power states, in which they may not be operational or
> even accessible, and go back to the fully operational state as needed.
> Power can be reduced this way without waiting for a transition into a
> system-wide sleep state."
Sure, looks fine to me.
> > +
> > +Core Concepts
> > +-------------
> > +
> > +Understanding runtime PM requires distinguishing between several pairs of
> > +related but distinct concepts that apply to each device: **enabled** /
> > +**disabled**, **active** / **suspended**, and **allowed** / **forbidden**.
> > +
> > +* **Enabled**: To use runtime PM to manage a device's power states, it must
> > + first be **enabled**. If RPM is never enabled for a device, it generally
> > + stays inactive from an RPM perspective, and the PM core will ignore it.
> > + If it is enabled, the PM core can manage the device status (see **Active**
> > + below) according to its understanding of whether the device is in use, and
> > + perform state transitions via the appropriate PM callbacks
> > + (->runtime_suspend(), ->runtime_resume()).
> > +
> > + Each device has an internal disable counter (``disable_depth``) which
> > + determines whether runtime PM is currently enabled. Devices are initially
> > + registered with runtime PM disabled (``disable_depth == 1``), though some bus
> > + types (such as PCI) may enable it before driver probe.
> > +
> > + To opt into runtime PM, a driver first ensures that the device's recorded
> > + status matches its actual physical state (for example, by calling
> > + pm_runtime_set_active() if the device was powered on at probe) and then calls
> > + pm_runtime_enable(), decrementing ``disable_depth`` to zero (i.e.,
> > + **enabled**). Runtime PM may be disabled again explicitly via
> > + pm_runtime_disable() or temporarily during system sleep transitions.
> > +
> > +* **Active**: The PM core tracks a device's runtime status as either **active**
> > + (the device is operational, having completed its resume callback or otherwise
> > + marked active) or **suspended** (the device is idle or in a low-power state,
> > + having completed its suspend callback or otherwise marked suspended), along
> > + with transitional **suspending** and **resuming** phases. When runtime PM is
> > + **enabled**, state transitions are primarily driven by reference counting:
> > + drivers call pm_runtime_resume_and_get() (or related variants) before using
> > + the hardware, to ensure the device is active; and pm_runtime_put() (or
> > + related variants) once work completes. When a device's usage counter drops to
> > + zero and its dependencies (children or consumers) are suspended, the PM core
> > + can suspend the device immediately or after an autosuspend delay.
> > +
> > + Besides driving the state of the device in question, a device's runtime
> > + status also affects those of its dependencies — its parent (if the parent's
> > + ``power.ignore_children`` is false) and its linked supplier device(s) (for
> > + links with the ``DL_FLAG_PM_RUNTIME`` flag). An **active** device holds
> > + reference counts on its dependencies, preventing them from suspending.
> > +
> > +* **Allowed**: System policy and user space govern whether dynamic suspension
> > + is permitted through the concepts of **allowed** and **forbidden**,
> > + manipulated in-kernel via pm_runtime_allow() and pm_runtime_forbid() and
> > + exposed to user space through the ``/sys/devices/.../power/control``
> > + attribute. When runtime PM is forbidden (``control`` set to ``on``), the PM
> > + core increments the device's usage counter, forcing the device to remain
> > + active regardless of whether the driver is idle. When runtime PM is allowed
> > + (``control`` set to ``auto``), this reference is dropped, permitting the PM
> > + core to automatically suspend the device whenever its driver and child
> > + devices are no longer using it.
> > +
> > +Notably, runtime PM also has a feature called "autosuspend." This is different
> > +than the ``control`` notion of "auto" (i.e., "allowed"). Autosuspend is
> > +described in more detail in `Section 9`_.
>
> Regarding the above, I have reconsidered it with the conclusion that
> it would be better to describe "active" and "suspended" first and
> "enabled" and "disabled" subsequently,
I also found it to be not-so-great to put "enabled" first, as it still
requires forward-references to "active" to cover it sufficiently.
> and maybe without going too
> much into details yet.
Sure. There are probably some details that could be omitted from my
version. Frankly, some of those details are there because you asked for
them though...
> Here's my version of it:
Thanks! My general thoughts are:
1) I think your version adds a few things that are nice to have. For
example, a better clarification of what "active" and "suspended" mean
from both physical device level, and from abstract RPM meaning. (This
may also be where you've insisted on "meta-state" as a term. I don't
agree that "meta" adds any value, but I won't insist.)
I also think the "forbidden" implication is a good addition: "the
ability to transition a device into the suspended meta-state via
runtime PM must not be relied on for correctness" -- that's one
reason I wanted to put allowed/forbidden up top; that it throws a
wrench in many people's assumptions.
You spend more time on dependencies. That's a good thing IMO.
2) I think your version adds some things that are undesirable for an
intro. For one, it spends quite some time to talk about the pitfalls
of a "disabled+active" device. I think this is not something that
goes in an introduction, and is more of an anti-pattern. If we wanted
to document anti-patterns, we could write another few essays, I'm
sure... It's also somewhat covered in Section 5 already.
You've also completely omitted describing reference counting. This is
one of the most fundamental aspects of RPM, IMO. (OTOH, omitting API
names is a fine choice.) I think your elaboration of "dependencies"
is a good time to just break out a section on what constitutes "in
use" -- get()/put() references, and dependents.
3) Lack of organizational clarity -- your version looks more like a wall
of text essay, which IMO doesn't do so well at engaging introductory
readers, or those skimming for one concept (e.g., "forbidden"). I
still prefer the structure that clearly highlights the main topics,
either with bullets or sections or something.
4) autosuspend -- I think it deserves a mention in the intro, even if
it's a pointer to the existing section. Not sure if you meant to drop
it.
5) Wordy. Your intro has about ~%50% more words. I think the same
content could be represented more succinctly, to make for a better
read.
...but:
6) It's better than not having this introduction at all!
So aside from the general thoughts above, I will:
(a) add minimal direct feedback to the text below, in case you'd still
prefer taking a variation of your content. That would be OK with me.
(b) provide my own adaptation of my writing + your writing at the end,
in case you'd rather try that.
> "There are some device-level concepts that need to be grasped in order
> to understand runtime PM as a whole.
I think listing the concepts at the top helps, as a sort of introductory
paragraph/sentence to the following wall of text and/or bullets.
Also, super-nits: you seem to wrap at about 70 chars, while most of this
doc (and other docs, I think) wraps at around 78-80.
I also see a difference on two spaces after periods or not. I guess most
of this doc uses two, even though that's not the dominant style these
days. I'll try to stick with two spaces now that I noticed. (Fun fact:
it seems browsers automatically collapse these to one space, when
viewing the generated HTML.)
> First of all, runtime PM tracks whether or not devices are in active
> use, which generally means that they are accessible and operational,
> and may be depended on by something (for example, other devices or
> user space). That is represented by the **active** meta-state of a
> device from the runtime PM perspective. The other persistent device
> meta-state used by runtime PM, called **suspended**, represents a
> promise that the given device will not be accessed. This covers
> devices in low-power states, but it also may include devices that are
> not fully operational, or are regarded as such, for other reasons.
> There are also two transient meta-states, **suspending** and
> **resuming**, that represent transitions between **active** and
> **suspended** often referred to as *runtime suspend* and *runtime
> resume*, or just *suspend* and *resume*, respectively. Every device
> handled by runtime PM is in one of these four meta-states at any time
> and the meta-state it is in is expected to reflect its actual physical
> configuration (that is, for instance, if the device is not accessible,
> it cannot be **active**). The term "runtime PM state" used in what
Somewhat nitpick: everything else seems to call it "runtime PM status"
or similar, not "runtime PM state". `enum rpm_status`, most of the
existing doc language, the 'power.runtime_status' field, etc.
> follows refers to the meta-states described above.
>
> Second, in order to track the runtime PM state and carry out
> transitions between **active** and **suspended**, runtime PM needs to
> be **enabled** for the given device. If it is **disabled**, it
> generally leaves the device alone. This means in particular that the
> runtime PM state of a device and its actual physical configuration may
> get out of sync after disabling runtime PM for it. Analogously, the
I'm not sure "analogously" is the right word here. It seems like you're
going for "additionally" or some other similar word.
> runtime PM state of a device may need to be explicitly adjusted to
> reflect its current physical configuration before enabling runtime PM
> for it. Moreover, it is generally not recommended to leave devices in
> the **active** meta-state after disabling runtime PM for them because
> that may affect what can be done to their ancestors and suppliers
> going forward.
>
> More specifically, in addition to tracking the runtime PM state of
> every device, runtime PM tracks dependencies between different
> devices. In fact, that dependency tracking mechanism is the main
> reason for using runtime PM. The idea is that in order for a device
> to become **active**, all of the devices it depends on must also be
> **active** and that is enforced by runtime PM. Accordingly, an
> attempt to resume a device causes all of the devices it depends on to
> become **active** and remain **active** until the given device is
> suspended. In turn, an attempt to suspend a device may allow the
> devices it depends on to also suspend unless they are additionally
> depended on by something else. While desirable so long as runtime PM
> is **enabled**, this may become problematic when runtime PM is
> **disabled** because the tracking of dependencies does not stop
> automatically at that point and it may cause some devices to remain
> **active** unnecessarily.
Like I said above, I like that you went into more detail on
dependencies. But I think this is a pretty divergent train of thought.
In my edited version below, I chose to break it out into a new
bullet/section, kept after the first 3.
> As a rule, runtime PM is **disabled** for all devices to start with,
> but there are bus types that enable it for every device (for instance,
> the PCI bus type does so). Generally speaking, drivers are expected
> to know which bus they belong to and so they should also know whether
> or not runtime PM has been enabled for the devices handled by them
> already. In the cases in which runtime PM is not enabled by the bus
> type, drivers are responsible for enabling it if they want to
> participate in it. The devices for which runtime PM has never been
> enabled are black boxes from its point of view.
I think most of this paragraph is a bit too much, and is easily derived
from just explaining that "most start disabled; some buses (like PCI)
make more initial choices for you; choose accordingly".
I'm also not sure what the "black box" mention adds on top of the
earlier, "If it is **disabled**, it generally leaves the device alone."
> Finally, runtime PM may be **forbidden** even though it has been
> enabled. Doing so causes the given device to transition into the
> **active** meta-state (unless it has been **active** already before)
> and prevents it from being suspended. In other words, a device with
> forbidden runtime PM remains **active** at least until runtime PM is
> **allowed** for it again. This mechanism is not only available to
> kernel code, but it may also be used by user space through the
> ``/sys/devices/.../power/control`` *sysfs* attribute of the given
> device. Namely, writing ``on`` to that attribute causes runtime PM to
> be forbidden for it, and writing ``auto`` to that attribute causes
> runtime PM to be allowed. User space may use that attribute at any
> time, so the ability to transition a device into the **suspended**
> meta-state via runtime PM must not be relied on for correctness, among
> other things."
I still think autosuspend belongs in the intro, even if only to link to
the existing section. (I also think the "auto" vs "autosuspend"
disambiguation is important, but I'm also open to moving that part to
Section 9 or similar.)
> I think that it provides all of the information needed to start with
> without pulling too much stuff documented elsewhere.
>
> If you agree with the above, I'll send my version as a separate patch.
I'm obviously biased, but I think there's room for improvement. I'm
providing my adaptation of your text below, but I'm also open to yours
however you see fit. Like I said, one of these options is better than
none.
Let me know if I should send the below in v4, or else please mail your
own for review!
"""
Runtime PM operates around a few device-level concepts — whether a device is
**active** or **suspended**; whether runtime PM is **enabled** or **disabled**;
whether runtime PM is **allowed** or **forbidden**; and whether a device is "in
use."
* **Active**: Runtime PM tracks whether or not devices are in active use, which
generally means that they are accessible and operational, and may be depended
on by something (for example, other devices or user space). This is
represented by the **active** meta-state. By contrast, the **suspended**
meta-state represents a promise that the given device will not be accessed.
This covers devices in low-power states, but it also may include devices that
are not fully operational. There are also two transient meta-states,
**suspending** and **resuming**, representing transitions between **active**
and **suspended** often referred to as *runtime suspend* and *runtime
resume*, or just *suspend* and *resume*, respectively. Every device handled
by runtime PM is in one of these four meta-states at any time, and its
meta-state is expected to reflect its actual physical configuration (that is,
for instance, if the device is not accessible, it must not be **active**).
The term "runtime PM status" used in what follows refers to the meta-states
described above.
* **Enabled**: In order to track the runtime PM status and carry out
transitions between **active** and **suspended**, runtime PM needs to be
**enabled** for the given device. If it is **disabled**, runtime PM
generally leaves the device alone. This means in particular that the runtime
PM status of a device and its actual physical configuration may get out of
sync after disabling runtime PM for it. Additionally, the runtime PM status
of a device may need to be explicitly adjusted to reflect its current
physical configuration before enabling runtime PM for it (e.g., during device
probe). Once runtime PM is **enabled**, it begins managing PM status —
performing *runtime suspend* and *runtime resume* transitions based on its
understanding of whether a device is in use.
As a rule, all devices are initialized with runtime PM **disabled**, though
some bus types (such as PCI) manage some RPM initialization automatically,
and therefore probe devices in an **enabled** state. For other devices,
drivers must enable runtime PM on their own to opt in.
* **Allowed**: Runtime PM may be **forbidden** even though it has been enabled.
Doing so causes the given device to transition into the **active** meta-state
and prevents it from being suspended. In other words, a device with
forbidden runtime PM remains **active** at least until runtime PM is
**allowed** for it again. This mechanism can be managed by in-kernel APIs,
but more importantly, it is also available to user space via the
``/sys/devices/.../power/control`` sysfs attribute of the given device.
Namely, writing ``on`` to that attribute forbids runtime PM, and writing
``auto`` allows it. User space may modify that attribute at any time, so the
ability to transition a device into the **suspended** meta-state via runtime
PM must not be relied on for correctness.
* **In use**: Runtime PM determines whether a device should be transitioned to
an **active** state by its understanding of whether a device is in use. The
first way a device is considered **in use** is by its own usage count — a
reference counter driven by a variety of get()/put() APIs. Additionally, a
device may be considered **in use** by having active dependents — either
child devices, or device-linked consumers. When a device is no longer in
use, runtime PM may choose to transition it to the **suspended** state.
Thus, when a device moves from a **suspended** to an **active** state, it may
also cause its dependencies to resume. Conversely, suspending a device may
also cause its otherwise-unused dependencies to suspend.
* **Autosuspend**: Runtime PM also supports a feature called "autosuspend."
This is different than the ``control`` notion of "auto" (i.e., **allowed**).
Autosuspend is covered in `Section 9`_.
"""
Brian
> > +
> > +Implementation Structure
> > +------------------------
> > +
> > +Support for runtime power management is provided at the power management core
> > +(PM core) level by means of:
> >
> > * Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
> > - include/linux/pm.h).
> > + include/linux/pm.h). See `Section 2`_.
> > +
> > +* A number of runtime PM fields in the 'power' member of 'struct device' that
> > + can be used for synchronizing runtime PM operations with one another. These
> > + are covered in `Section 3`_.
> >
> > * 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.
> > + synchronization between them is taken care of by the PM core. Bus types and
> > + device drivers are encouraged to use these functions. They are covered in
> > + `Section 4`_.
> >
> > -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.
> > +* 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.
> >
> > .. _Section 2:
> >
> > --
>
> The last part above looks fine to me.
>
> Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-30 23:40 ` Brian Norris
@ 2026-10-01 12:59 ` Rafael J. Wysocki (Intel)
0 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-10-01 12:59 UTC (permalink / raw)
To: Brian Norris
Cc: Rafael J. Wysocki (Intel),
Pavel Machek, Doug Anderson, Ulf Hansson, linux-doc, linux-pm,
Len Brown, linux-kernel
On Thu, Oct 1, 2026 at 1:40 AM Brian Norris <briannorris@chromium.org> wrote:
>
> Hi Rafael,
>
> On Wed, Sep 30, 2026 at 05:41:56PM +0200, Rafael J. Wysocki (Intel) wrote:
> > On Wed, Sep 30, 2026 at 4:51 AM Brian Norris <briannorris@chromium.org> wrote:
[cut]
> > > +
> > > +Core Concepts
> > > +-------------
> > > +
> > > +Understanding runtime PM requires distinguishing between several pairs of
> > > +related but distinct concepts that apply to each device: **enabled** /
> > > +**disabled**, **active** / **suspended**, and **allowed** / **forbidden**.
> > > +
> > > +* **Enabled**: To use runtime PM to manage a device's power states, it must
> > > + first be **enabled**. If RPM is never enabled for a device, it generally
> > > + stays inactive from an RPM perspective, and the PM core will ignore it.
> > > + If it is enabled, the PM core can manage the device status (see **Active**
> > > + below) according to its understanding of whether the device is in use, and
> > > + perform state transitions via the appropriate PM callbacks
> > > + (->runtime_suspend(), ->runtime_resume()).
> > > +
> > > + Each device has an internal disable counter (``disable_depth``) which
> > > + determines whether runtime PM is currently enabled. Devices are initially
> > > + registered with runtime PM disabled (``disable_depth == 1``), though some bus
> > > + types (such as PCI) may enable it before driver probe.
> > > +
> > > + To opt into runtime PM, a driver first ensures that the device's recorded
> > > + status matches its actual physical state (for example, by calling
> > > + pm_runtime_set_active() if the device was powered on at probe) and then calls
> > > + pm_runtime_enable(), decrementing ``disable_depth`` to zero (i.e.,
> > > + **enabled**). Runtime PM may be disabled again explicitly via
> > > + pm_runtime_disable() or temporarily during system sleep transitions.
> > > +
> > > +* **Active**: The PM core tracks a device's runtime status as either **active**
> > > + (the device is operational, having completed its resume callback or otherwise
> > > + marked active) or **suspended** (the device is idle or in a low-power state,
> > > + having completed its suspend callback or otherwise marked suspended), along
> > > + with transitional **suspending** and **resuming** phases. When runtime PM is
> > > + **enabled**, state transitions are primarily driven by reference counting:
> > > + drivers call pm_runtime_resume_and_get() (or related variants) before using
> > > + the hardware, to ensure the device is active; and pm_runtime_put() (or
> > > + related variants) once work completes. When a device's usage counter drops to
> > > + zero and its dependencies (children or consumers) are suspended, the PM core
> > > + can suspend the device immediately or after an autosuspend delay.
> > > +
> > > + Besides driving the state of the device in question, a device's runtime
> > > + status also affects those of its dependencies — its parent (if the parent's
> > > + ``power.ignore_children`` is false) and its linked supplier device(s) (for
> > > + links with the ``DL_FLAG_PM_RUNTIME`` flag). An **active** device holds
> > > + reference counts on its dependencies, preventing them from suspending.
> > > +
> > > +* **Allowed**: System policy and user space govern whether dynamic suspension
> > > + is permitted through the concepts of **allowed** and **forbidden**,
> > > + manipulated in-kernel via pm_runtime_allow() and pm_runtime_forbid() and
> > > + exposed to user space through the ``/sys/devices/.../power/control``
> > > + attribute. When runtime PM is forbidden (``control`` set to ``on``), the PM
> > > + core increments the device's usage counter, forcing the device to remain
> > > + active regardless of whether the driver is idle. When runtime PM is allowed
> > > + (``control`` set to ``auto``), this reference is dropped, permitting the PM
> > > + core to automatically suspend the device whenever its driver and child
> > > + devices are no longer using it.
> > > +
> > > +Notably, runtime PM also has a feature called "autosuspend." This is different
> > > +than the ``control`` notion of "auto" (i.e., "allowed"). Autosuspend is
> > > +described in more detail in `Section 9`_.
> >
> > Regarding the above, I have reconsidered it with the conclusion that
> > it would be better to describe "active" and "suspended" first and
> > "enabled" and "disabled" subsequently,
>
> I also found it to be not-so-great to put "enabled" first, as it still
> requires forward-references to "active" to cover it sufficiently.
>
> > and maybe without going too
> > much into details yet.
>
> Sure. There are probably some details that could be omitted from my
> version. Frankly, some of those details are there because you asked for
> them though...
>
> > Here's my version of it:
>
> Thanks! My general thoughts are:
>
> 1) I think your version adds a few things that are nice to have. For
> example, a better clarification of what "active" and "suspended" mean
> from both physical device level, and from abstract RPM meaning. (This
> may also be where you've insisted on "meta-state" as a term. I don't
> agree that "meta" adds any value, but I won't insist.)
I just want to make it clear that "active" and "suspended" are
abstract and not tied to any specific device states in principle.
Maybe this is obvious.
> I also think the "forbidden" implication is a good addition: "the
> ability to transition a device into the suspended meta-state via
> runtime PM must not be relied on for correctness" -- that's one
> reason I wanted to put allowed/forbidden up top; that it throws a
> wrench in many people's assumptions.
>
> You spend more time on dependencies. That's a good thing IMO.
>
> 2) I think your version adds some things that are undesirable for an
> intro. For one, it spends quite some time to talk about the pitfalls
> of a "disabled+active" device. I think this is not something that
> goes in an introduction, and is more of an anti-pattern. If we wanted
> to document anti-patterns, we could write another few essays, I'm
> sure... It's also somewhat covered in Section 5 already.
Fair enough.
> You've also completely omitted describing reference counting.
Kind of on purpose because I didn't want to pull up too much internal stuff.
> This is one of the most fundamental aspects of RPM, IMO. (OTOH, omitting API
> names is a fine choice.) I think your elaboration of "dependencies"
> is a good time to just break out a section on what constitutes "in
> use" -- get()/put() references, and dependents.
>
> 3) Lack of organizational clarity -- your version looks more like a wall
> of text essay, which IMO doesn't do so well at engaging introductory
> readers, or those skimming for one concept (e.g., "forbidden"). I
> still prefer the structure that clearly highlights the main topics,
> either with bullets or sections or something.
This is a matter of personal preference.
> 4) autosuspend -- I think it deserves a mention in the intro, even if
> it's a pointer to the existing section. Not sure if you meant to drop
> it.
>
> 5) Wordy. Your intro has about ~%50% more words. I think the same
> content could be represented more succinctly, to make for a better
> read.
>
> ...but:
>
> 6) It's better than not having this introduction at all!
>
> So aside from the general thoughts above, I will:
>
> (a) add minimal direct feedback to the text below, in case you'd still
> prefer taking a variation of your content. That would be OK with me.
>
> (b) provide my own adaptation of my writing + your writing at the end,
> in case you'd rather try that.
>
> > "There are some device-level concepts that need to be grasped in order
> > to understand runtime PM as a whole.
>
> I think listing the concepts at the top helps, as a sort of introductory
> paragraph/sentence to the following wall of text and/or bullets.
>
> Also, super-nits: you seem to wrap at about 70 chars, while most of this
> doc (and other docs, I think) wraps at around 78-80.
>
> I also see a difference on two spaces after periods or not. I guess most
> of this doc uses two, even though that's not the dominant style these
> days. I'll try to stick with two spaces now that I noticed. (Fun fact:
> it seems browsers automatically collapse these to one space, when
> viewing the generated HTML.)
>
> > First of all, runtime PM tracks whether or not devices are in active
> > use, which generally means that they are accessible and operational,
> > and may be depended on by something (for example, other devices or
> > user space). That is represented by the **active** meta-state of a
> > device from the runtime PM perspective. The other persistent device
> > meta-state used by runtime PM, called **suspended**, represents a
> > promise that the given device will not be accessed. This covers
> > devices in low-power states, but it also may include devices that are
> > not fully operational, or are regarded as such, for other reasons.
> > There are also two transient meta-states, **suspending** and
> > **resuming**, that represent transitions between **active** and
> > **suspended** often referred to as *runtime suspend* and *runtime
> > resume*, or just *suspend* and *resume*, respectively. Every device
> > handled by runtime PM is in one of these four meta-states at any time
> > and the meta-state it is in is expected to reflect its actual physical
> > configuration (that is, for instance, if the device is not accessible,
> > it cannot be **active**). The term "runtime PM state" used in what
>
> Somewhat nitpick: everything else seems to call it "runtime PM status"
> or similar, not "runtime PM state". `enum rpm_status`, most of the
> existing doc language, the 'power.runtime_status' field, etc.
>
> > follows refers to the meta-states described above.
> >
> > Second, in order to track the runtime PM state and carry out
> > transitions between **active** and **suspended**, runtime PM needs to
> > be **enabled** for the given device. If it is **disabled**, it
> > generally leaves the device alone. This means in particular that the
> > runtime PM state of a device and its actual physical configuration may
> > get out of sync after disabling runtime PM for it. Analogously, the
>
> I'm not sure "analogously" is the right word here. It seems like you're
> going for "additionally" or some other similar word.
>
> > runtime PM state of a device may need to be explicitly adjusted to
> > reflect its current physical configuration before enabling runtime PM
> > for it. Moreover, it is generally not recommended to leave devices in
> > the **active** meta-state after disabling runtime PM for them because
> > that may affect what can be done to their ancestors and suppliers
> > going forward.
> >
> > More specifically, in addition to tracking the runtime PM state of
> > every device, runtime PM tracks dependencies between different
> > devices. In fact, that dependency tracking mechanism is the main
> > reason for using runtime PM. The idea is that in order for a device
> > to become **active**, all of the devices it depends on must also be
> > **active** and that is enforced by runtime PM. Accordingly, an
> > attempt to resume a device causes all of the devices it depends on to
> > become **active** and remain **active** until the given device is
> > suspended. In turn, an attempt to suspend a device may allow the
> > devices it depends on to also suspend unless they are additionally
> > depended on by something else. While desirable so long as runtime PM
> > is **enabled**, this may become problematic when runtime PM is
> > **disabled** because the tracking of dependencies does not stop
> > automatically at that point and it may cause some devices to remain
> > **active** unnecessarily.
>
> Like I said above, I like that you went into more detail on
> dependencies. But I think this is a pretty divergent train of thought.
> In my edited version below, I chose to break it out into a new
> bullet/section, kept after the first 3.
>
> > As a rule, runtime PM is **disabled** for all devices to start with,
> > but there are bus types that enable it for every device (for instance,
> > the PCI bus type does so). Generally speaking, drivers are expected
> > to know which bus they belong to and so they should also know whether
> > or not runtime PM has been enabled for the devices handled by them
> > already. In the cases in which runtime PM is not enabled by the bus
> > type, drivers are responsible for enabling it if they want to
> > participate in it. The devices for which runtime PM has never been
> > enabled are black boxes from its point of view.
>
> I think most of this paragraph is a bit too much, and is easily derived
> from just explaining that "most start disabled; some buses (like PCI)
> make more initial choices for you; choose accordingly".
>
> I'm also not sure what the "black box" mention adds on top of the
> earlier, "If it is **disabled**, it generally leaves the device alone."
>
> > Finally, runtime PM may be **forbidden** even though it has been
> > enabled. Doing so causes the given device to transition into the
> > **active** meta-state (unless it has been **active** already before)
> > and prevents it from being suspended. In other words, a device with
> > forbidden runtime PM remains **active** at least until runtime PM is
> > **allowed** for it again. This mechanism is not only available to
> > kernel code, but it may also be used by user space through the
> > ``/sys/devices/.../power/control`` *sysfs* attribute of the given
> > device. Namely, writing ``on`` to that attribute causes runtime PM to
> > be forbidden for it, and writing ``auto`` to that attribute causes
> > runtime PM to be allowed. User space may use that attribute at any
> > time, so the ability to transition a device into the **suspended**
> > meta-state via runtime PM must not be relied on for correctness, among
> > other things."
>
> I still think autosuspend belongs in the intro, even if only to link to
> the existing section. (I also think the "auto" vs "autosuspend"
> disambiguation is important, but I'm also open to moving that part to
> Section 9 or similar.)
>
> > I think that it provides all of the information needed to start with
> > without pulling too much stuff documented elsewhere.
> >
> > If you agree with the above, I'll send my version as a separate patch.
>
> I'm obviously biased, but I think there's room for improvement. I'm
> providing my adaptation of your text below, but I'm also open to yours
> however you see fit. Like I said, one of these options is better than
> none.
>
> Let me know if I should send the below in v4, or else please mail your
> own for review!
>
> """
> Runtime PM operates around a few device-level concepts — whether a device is
> **active** or **suspended**; whether runtime PM is **enabled** or **disabled**;
> whether runtime PM is **allowed** or **forbidden**; and whether a device is "in
> use."
>
> * **Active**: Runtime PM tracks whether or not devices are in active use, which
> generally means that they are accessible and operational, and may be depended
> on by something (for example, other devices or user space). This is
> represented by the **active** meta-state. By contrast, the **suspended**
So you can just drop the "meta-" prefix here and elsewhere below if
you think that the meaning of "state" is clear enough. It's up to you
though.
> meta-state represents a promise that the given device will not be accessed.
> This covers devices in low-power states, but it also may include devices that
> are not fully operational. There are also two transient meta-states,
> **suspending** and **resuming**, representing transitions between **active**
> and **suspended** often referred to as *runtime suspend* and *runtime
> resume*, or just *suspend* and *resume*, respectively. Every device handled
> by runtime PM is in one of these four meta-states at any time, and its
> meta-state is expected to reflect its actual physical configuration (that is,
> for instance, if the device is not accessible, it must not be **active**).
> The term "runtime PM status" used in what follows refers to the meta-states
> described above.
>
> * **Enabled**: In order to track the runtime PM status and carry out
> transitions between **active** and **suspended**, runtime PM needs to be
> **enabled** for the given device. If it is **disabled**, runtime PM
> generally leaves the device alone. This means in particular that the runtime
> PM status of a device and its actual physical configuration may get out of
> sync after disabling runtime PM for it. Additionally, the runtime PM status
> of a device may need to be explicitly adjusted to reflect its current
> physical configuration before enabling runtime PM for it (e.g., during device
> probe). Once runtime PM is **enabled**, it begins managing PM status —
> performing *runtime suspend* and *runtime resume* transitions based on its
> understanding of whether a device is in use.
>
> As a rule, all devices are initialized with runtime PM **disabled**, though
> some bus types (such as PCI) manage some RPM initialization automatically,
> and therefore probe devices in an **enabled** state. For other devices,
> drivers must enable runtime PM on their own to opt in.
>
> * **Allowed**: Runtime PM may be **forbidden** even though it has been enabled.
> Doing so causes the given device to transition into the **active** meta-state
> and prevents it from being suspended. In other words, a device with
> forbidden runtime PM remains **active** at least until runtime PM is
> **allowed** for it again. This mechanism can be managed by in-kernel APIs,
> but more importantly, it is also available to user space via the
> ``/sys/devices/.../power/control`` sysfs attribute of the given device.
> Namely, writing ``on`` to that attribute forbids runtime PM, and writing
> ``auto`` allows it. User space may modify that attribute at any time, so the
> ability to transition a device into the **suspended** meta-state via runtime
> PM must not be relied on for correctness.
>
> * **In use**: Runtime PM determines whether a device should be transitioned to
> an **active** state by its understanding of whether a device is in use. The
> first way a device is considered **in use** is by its own usage count — a
> reference counter driven by a variety of get()/put() APIs. Additionally, a
> device may be considered **in use** by having active dependents — either
> child devices, or device-linked consumers. When a device is no longer in
> use, runtime PM may choose to transition it to the **suspended** state.
>
> Thus, when a device moves from a **suspended** to an **active** state, it may
I would say "from **suspended** to **active**" here
> also cause its dependencies to resume.
Also, I'd say "it causes its dependencies to resume unless they are
**active** already"
> Conversely, suspending a device may
> also cause its otherwise-unused dependencies to suspend.
>
> * **Autosuspend**: Runtime PM also supports a feature called "autosuspend."
> This is different than the ``control`` notion of "auto" (i.e., **allowed**).
> Autosuspend is covered in `Section 9`_.
> """
Apart from the nits above, this looks fine to me. Please feel free to
send a v4.
Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-01 13:00 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-30 2:49 [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-30 2:49 ` [PATCH v3 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
2026-09-30 2:49 ` [PATCH v3 2/8] PM: runtime: More kerneldoc formatting Brian Norris
2026-09-30 2:49 ` [PATCH v3 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
2026-09-30 2:49 ` [PATCH v3 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
2026-09-30 2:49 ` [PATCH v3 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
2026-09-30 2:49 ` [PATCH v3 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
2026-09-30 2:49 ` [PATCH v3 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
2026-09-30 15:41 ` Rafael J. Wysocki (Intel)
2026-09-30 23:40 ` Brian Norris
2026-10-01 12:59 ` Rafael J. Wysocki (Intel)
2026-09-30 15:44 ` Ulf Hansson
2026-09-30 2:49 ` [PATCH v3 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
2026-09-30 12:56 ` [PATCH v3 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Rafael J. Wysocki (Intel)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®