* [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs
@ 2026-09-23 17:40 Brian Norris
2026-09-23 17:40 ` [PATCH v2 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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.
Find version 1 of this series here:
https://lore.kernel.org/all/20260904212000.4167880-1-briannorris@chromium.org/
The first part of that 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 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 | 568 ++++++++++++++++++++++++++---
drivers/base/power/runtime.c | 8 +-
2 files changed, 525 insertions(+), 51 deletions(-)
--
2.56.0.rc1.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 2/8] PM: runtime: More kerneldoc formatting Brian Norris
` (6 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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>
---
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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 2/8] PM: runtime: More kerneldoc formatting
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-23 17:40 ` [PATCH v2 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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 v2:
* New in v2
drivers/base/power/runtime.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 7e75f6d5df07..dce7b6ff7e9d 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1255,7 +1255,7 @@ 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
+ * in active state.
* @dev: Target device.
*
* Increment the runtime PM usage counter of @dev if its runtime PM status is
@@ -1635,10 +1635,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)
{
--
2.56.0.rc1.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-23 17:40 ` [PATCH v2 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
2026-09-23 17:40 ` [PATCH v2 2/8] PM: runtime: More kerneldoc formatting Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-24 14:01 ` Ulf Hansson
2026-09-23 17:40 ` [PATCH v2 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
` (4 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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>
---
(no changes since v1)
Documentation/power/runtime_pm.rst | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 39fdeeda7a1e..352cdaf0650d 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -238,6 +238,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 +252,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 +262,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 +291,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 +319,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 +433,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 +448,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 +512,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 +522,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 +565,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 +581,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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 4/8] PM: runtime: Add "Section" hyperlinks
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (2 preceding siblings ...)
2026-09-23 17:40 ` [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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>
---
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 352cdaf0650d..114c4a872cb1 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
=====================================
@@ -257,12 +265,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.
@@ -285,7 +295,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().
@@ -336,6 +346,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
==============================
@@ -428,6 +440,8 @@ out the following operations:
callback and right after executing the subsystem-level .complete() callback
for it, respectively.
+.. _Section 7:
+
7. Generic subsystem callbacks
==============================
@@ -451,6 +465,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
========================
@@ -487,6 +503,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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (3 preceding siblings ...)
2026-09-23 17:40 ` [PATCH v2 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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 114c4a872cb1..423287fce34a 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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (4 preceding siblings ...)
2026-09-23 17:40 ` [PATCH v2 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
2026-09-23 17:40 ` [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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 423287fce34a..e0c20132dabd 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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 7/8] PM: runtime: Expand introduction with core concepts and structure
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (5 preceding siblings ...)
2026-09-23 17:40 ` [PATCH v2 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
7 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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>
---
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 e0c20132dabd..7bb64d793cdd 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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
` (6 preceding siblings ...)
2026-09-23 17:40 ` [PATCH v2 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
@ 2026-09-23 17:40 ` Brian Norris
2026-09-24 14:13 ` Ulf Hansson
7 siblings, 1 reply; 12+ messages in thread
From: Brian Norris @ 2026-09-23 17:40 UTC (permalink / raw)
To: Rafael J . Wysocki
Cc: linux-doc, linux-pm, Ulf Hansson, Len Brown, Pavel Machek,
Doug Anderson, 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 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 | 367 ++++++++++++++++++++++++++++-
1 file changed, 366 insertions(+), 1 deletion(-)
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 7bb64d793cdd..3a615d2de103 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -641,7 +641,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)
{
@@ -707,3 +709,366 @@ 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 device-managed 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;
+
+ /* 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);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Alternatively, the above two calls can be combined into:
+ * ret = devm_pm_runtime_set_active_enabled(dev);
+ * if (ret)
+ * return ret;
+ */
+
+ /*
+ * 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;
+ }
+
+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);
+ 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);
+ }
+
+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``.
+
+Drivers using this pattern should also ensure that hardware is powered off
+cleanly upon driver unbind. If the device was still active when detached (for
+example, if user space configured ``/sys/devices/.../power/control`` to
+``on``, or if an operation was ongoing), the ->remove() callback disables
+runtime PM, checks whether the device is not yet suspended using
+pm_runtime_status_suspended(), and manually invokes foo_runtime_suspend().
+
+Autosuspend Probe
+~~~~~~~~~~~~~~~~~
+
+If the driver uses autosuspend, it configures the autosuspend delay and enables
+autosuspend before enabling runtime PM:
+
+.. 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;
+
+ /* Power on and initialize hardware registers... */
+
+ /* Set autosuspend delay (e.g. 2000 ms) and enable autosuspend */
+ pm_runtime_set_autosuspend_delay(dev, 2000);
+ pm_runtime_use_autosuspend(dev);
+
+ pm_runtime_set_active(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;
+ }
+
+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.310.g51773c2048-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst
2026-09-23 17:40 ` [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
@ 2026-09-24 14:01 ` Ulf Hansson
2026-09-24 16:56 ` Brian Norris
0 siblings, 1 reply; 12+ messages in thread
From: Ulf Hansson @ 2026-09-24 14:01 UTC (permalink / raw)
To: Brian Norris
Cc: Rafael J . Wysocki, linux-doc, linux-pm, Ulf Hansson, Len Brown,
Pavel Machek, Doug Anderson, linux-kernel
On Wed, Sep 23, 2026 at 7:47 PM Brian Norris <briannorris@chromium.org> wrote:
>
> 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>
> ---
>
> (no changes since v1)
>
> Documentation/power/runtime_pm.rst | 27 +++++++++++++++++----------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> index 39fdeeda7a1e..352cdaf0650d 100644
> --- a/Documentation/power/runtime_pm.rst
> +++ b/Documentation/power/runtime_pm.rst
> @@ -238,6 +238,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 +252,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 +262,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 +291,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 +319,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.
As I have stated in earlier discussions at LKML, the
devm_pm_runtime_enable() API is not entirely easy to use correctly by
drivers. It means that pm_runtime_disable() gets called at some point
*after* the ->remove() callback has been invoked, which can cause
problems, unless the driver's ->remove() callback has managed things
correctly.
My point is, the above makes it sounds like it's easy to switch to the
devm managed version, while it certainly isn't that straight forward.
Not sure what that means for the documentation though. :-)
[...]
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section
2026-09-23 17:40 ` [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
@ 2026-09-24 14:13 ` Ulf Hansson
0 siblings, 0 replies; 12+ messages in thread
From: Ulf Hansson @ 2026-09-24 14:13 UTC (permalink / raw)
To: Brian Norris
Cc: Rafael J . Wysocki, linux-doc, linux-pm, Ulf Hansson, Len Brown,
Pavel Machek, Doug Anderson, linux-kernel
On Wed, Sep 23, 2026 at 7:48 PM Brian Norris <briannorris@chromium.org> wrote:
>
> 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 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 | 367 ++++++++++++++++++++++++++++-
> 1 file changed, 366 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> index 7bb64d793cdd..3a615d2de103 100644
> --- a/Documentation/power/runtime_pm.rst
> +++ b/Documentation/power/runtime_pm.rst
> @@ -641,7 +641,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)
> {
> @@ -707,3 +709,366 @@ 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 device-managed 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;
> +
> + /* 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);
> +
> + ret = devm_pm_runtime_enable(dev);
> + if (ret)
> + return ret;
> +
> + /*
> + * Alternatively, the above two calls can be combined into:
> + * ret = devm_pm_runtime_set_active_enabled(dev);
> + * if (ret)
> + * return ret;
> + */
> +
> + /*
> + * 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;
The above looks nice and simple, but what happens in the error path is
equally important.
In principle, nothing prevents the runtime PM callbacks to be invoked
until pm_runtime_disable() has been called at some point *after* the
probe callback has returned. This needs to be taken care of correctly.
Likewise, as it's great with an example for ->probe(), it would be
nice with a corresponding example for ->remove().
I will have to defer reviewing the remaining parts in the $subject
patch, a bit limited bandwidth at the moment.
[...]
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst
2026-09-24 14:01 ` Ulf Hansson
@ 2026-09-24 16:56 ` Brian Norris
0 siblings, 0 replies; 12+ messages in thread
From: Brian Norris @ 2026-09-24 16:56 UTC (permalink / raw)
To: Ulf Hansson
Cc: Rafael J . Wysocki, linux-doc, linux-pm, Ulf Hansson, Len Brown,
Pavel Machek, Doug Anderson, linux-kernel
On Thu, Sep 24, 2026 at 04:01:00PM +0200, Ulf Hansson wrote:
> On Wed, Sep 23, 2026 at 7:47 PM Brian Norris <briannorris@chromium.org> wrote:
> > diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
> > index 39fdeeda7a1e..352cdaf0650d 100644
> > --- a/Documentation/power/runtime_pm.rst
> > +++ b/Documentation/power/runtime_pm.rst
> > @@ -315,7 +319,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.
>
> As I have stated in earlier discussions at LKML, the
> devm_pm_runtime_enable() API is not entirely easy to use correctly by
> drivers. It means that pm_runtime_disable() gets called at some point
> *after* the ->remove() callback has been invoked, which can cause
> problems, unless the driver's ->remove() callback has managed things
> correctly.
Yeah. And I think it's rare for drivers to have done a thorough job. A
rare exception: I found commit 2d90ecdfa326 ("ASoC: rockchip: i2s: Use
managed hclk and runtime PM cleanup") an interesting outlier -- it adds
an additional devres teardown to power things off afterward.
OTOH, between v1 and v2, I chose to tweak one of the Examples to avoid
devm, precisely because it was committing (or hinting at) these kinds of
mistakes.
> My point is, the above makes it sounds like it's easy to switch to the
> devm managed version, while it certainly isn't that straight forward.
Right, I said as much in the cover letter too:
(possible future work)
<quote>
* 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.
</quote>
Would this be a good moment to pass this possibility by you? What if we
taught the teardown to force a device back to RPM_SUSPENDED? Something
like:
static void pm_runtime_disable_action(void *data)
{
pm_runtime_dont_use_autosuspend(data);
pm_runtime_disable(data);
// New code:
if (pm_runtime_status_suspended(data)) {
int (*callback)(struct device *);
int ret;
callback = GET_CALLBACK(data, runtime_suspend);
ret = callback ? callback(data) : 0;
if (ret)
return;
pm_runtime_set_suspended(data);
}
}
> Not sure what that means for the documentation though. :-)
Well, I don't feel like the part you quoted is a problem. IMO, it's
totally fair to mention relevant APIs even if they're hard to use --
there is no part of the runtime PM that is easy to use!
But I'm definitely trying to make things easier too. Ideally, we can do
something like the above to make it easier to use. But if we
can't...well, I guess I can try to document pitfalls better -- possibly
in the Examples section, or maybe an extra note in the above quoted
area.
Thanks for looking,
Brian
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-09-24 16:56 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-23 17:40 [PATCH v2 0/8] PM: runtime: Overhaul kerneldoc, runtime_pm.rst docs Brian Norris
2026-09-23 17:40 ` [PATCH v2 1/8] PM: runtime: Correct pm_runtime_autosuspend_expiration() doc Brian Norris
2026-09-23 17:40 ` [PATCH v2 2/8] PM: runtime: More kerneldoc formatting Brian Norris
2026-09-23 17:40 ` [PATCH v2 3/8] PM: runtime: Misc improvements to runtime_pm.rst Brian Norris
2026-09-24 14:01 ` Ulf Hansson
2026-09-24 16:56 ` Brian Norris
2026-09-23 17:40 ` [PATCH v2 4/8] PM: runtime: Add "Section" hyperlinks Brian Norris
2026-09-23 17:40 ` [PATCH v2 5/8] PM: runtime: Clarify ->runtime_idle() callback return value handling Brian Norris
2026-09-23 17:40 ` [PATCH v2 6/8] PM: runtime: Clarify driver callback expectations and structure Section 2 Brian Norris
2026-09-23 17:40 ` [PATCH v2 7/8] PM: runtime: Expand introduction with core concepts and structure Brian Norris
2026-09-23 17:40 ` [PATCH v2 8/8] PM: runtime: Add Example Driver Patterns section Brian Norris
2026-09-24 14:13 ` Ulf Hansson
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®