From: Brian Norris <briannorris@chromium.org>
To: Jonathan Cameron <jic23@kernel.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>,
"Fabrice Gasnier" <fabrice.gasnier@st.com>,
linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
"Ulf Hansson" <ulfh@kernel.org>,
linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org,
"Andy Shevchenko" <andy@kernel.org>,
"David Lechner" <dlechner@baylibre.com>,
"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Maxime Coquelin" <mcoquelin.stm32@gmail.com>
Subject: Re: [PATCH v2 3/5] PM: runtime: Propagate last_busy from dependent to dependency
Date: Tue, 3 Nov 2026 16:32:44 -0800 [thread overview]
Message-ID: <aup9LKewaLr2B5cR@google.com> (raw)
In-Reply-To: <20261103231719.486a18de@jic23-hlaptop>
Hi Jonathan,
On Tue, Nov 03, 2026 at 11:17:19PM +0000, Jonathan Cameron wrote:
> On Tue, 3 Nov 2026 14:14:41 -0800
> Brian Norris <briannorris@chromium.org> wrote:
>
> > When a child device suspends, it does not update the last_busy timestamp
> > for its parent. If that parent configured autosuspend and didn't
> > otherwise maintain its last_busy timestamp, it may now be immediately
> > eligible to suspend. This is probably not expected -- the parent should
> > wait for its autosuspend delay before suspending.
>
> So reading this again - I wonder if this text is describing the
> expected behaviour.
Agreed, this might give the wrong impression, depending on the
assumptions the reader makes about autosuspend delay. (I think I had a
particular problem scenario in mind, but didn't translate that properly
here.)
> If the child is also using autosupend then, in extreme case, that time
> might be longer than the autosuspend time of the parent.
> If so it seems odd the parent still waits.
Right, that seems wrong, and indeed that's not what this patch does.
> So most expected to me
> would be if the parent were to suspend it's autosuspend time after
> the parent or child was last used for something that indicate a
> desire not to suspend (that shouldn't include actions the child
> did whilst suspending).
(Not sure I'm parsing this sentence quite right, but...)
The point is that last_busy should propagate (rather than, say, the
expiration time). So each device still gets its own-delay-based
autosuspend timer expiration. That may mean the parent waits longer than
the child, but it may not, if the child's delay was longer than the
parent's.
> Maybe there isn't a sensible way to deal with this and what you have here
> is the best we can do. Note that this is just commenting on this
> statement in the commit description. From what follows I think
> this is just a commit description thing rather than functional.
If I'm understanding what you're saying correctly: maybe it would be an
improvement here to say:
If that parent configured an autosuspend delay longer than its child's
and didn't otherwise maintain its last_busy timestamp, it may now be
immediately eligible to suspend.
I think that would more accurately describe the target problem, even if
it doesn't cover all cases (such as when the parent delay is shorter).
> > The effect of this behavior is that a parent device may suspend sooner
> > than its autosuspend delay, simply because its usage was accounted by
> > its children, and not by direct references to the parent device.
>
> Sooner is indeed bad.
>
> >
> > This was noticed in several cases, and some have implemented
> > workarounds, such as in commit c537d3457542 ("iio: adc: stm32-adc: fix
> > runtime autosuspend delay when slow polling"). At the same time, Ulf
> > suggested these problems "should be solved in the runtime PM core" [1].
> >
> > Instead of working around the problem in drivers, we propagate last_busy
> > timestamps from a dependent device to its dependencies any time it may
> > allow a dependency to suspend -- i.e., when releasing a refcount for its
> > parent or suppliers. We take care to only propagate the timestamp if it
> > is larger than the existing busy timestamp.
>
> So this sounds fine but I don't think aligns with that first paragraph.
>
> >
> > Note that this works best if the dependent device is using autosuspend
> > (and therefore updates its last_busy timestamps appropriately), but even
> > for a non-autosuspend child, this is still somewhat useful --
> > non-autosuspend devices still automatically update their last_busy every
> > time they resume.
>
> Can we set the last busy on the suspend of child devices that aren't
> suspending as a result of autosuspend timeout but for other reasons?
> (may be some fiddly corners!)
Do you have concrete use cases in mind, or do you bring this up simply
because of my note?
For one, I feel like for devices with power.use_autosuspend==true, it's
reasonable to expect drivers to use the appropriate helpers to update
last_busy at the appropriate times, and so any "corner cases" are from
misuse.
But if you mean non-use_autosuspend devices: I suppose it'd be possible
but I haven't reasoned through the implementation very far yet. It
almost seems like we'd need to plumb pm_runtime_mark_last_busy() into
*all* the put() helpers, including the non-autosuspend ones
(pm_runtime_put(), pm_runtime_put_sync()). I'm not quite sure if that's
desirable. But I could try to look a bit more, if you think there are
important use cases that would need this.
Brian
> > Link: https://lore.kernel.org/all/CAPDyKFp=KTf8=zGBSzPYqhjnZpY8xwvjCeM1e-WTKT1QLSxaDA@mail.gmail.com/ [1]
> > Signed-off-by: Brian Norris <briannorris@chromium.org>
> > ---
> > Cc: Ulf Hansson <ulfh@kernel.org>
> >
> > Changes in v2:
> > * Update comments to explain when/why rpm_propagate_last_busy()
> > performs the update
> >
> > drivers/base/power/runtime.c | 23 ++++++++++++++++++++++-
> > 1 file changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
> > index 2a117d6a776f..dd306cbabcd3 100644
> > --- a/drivers/base/power/runtime.c
> > +++ b/drivers/base/power/runtime.c
> > @@ -318,6 +318,22 @@ static int rpm_get_suppliers(struct device *dev)
> > return 0;
> > }
> >
> > +/*
> > + * Propagate last_busy timestamp from one device to another, typically when a
> > + * device (@dev) releases a reference count on a dependency (@target) and might
> > + * allow it to (auto)suspend. This can, for example, prevent overactive suspend
> > + * when a dependency's usage is primarily driven by one of its dependents.
> > + */
> > +static void rpm_propagate_last_busy(struct device *dev, struct device *target)
> > +{
> > + s64 busy = atomic64_read(&dev->power.last_busy);
> > + s64 target_busy = atomic64_read(&target->power.last_busy);
> > +
> > + while (target_busy < busy)
> > + if (atomic64_try_cmpxchg(&target->power.last_busy, &target_busy, busy))
> > + return;
> > +}
> > +
> > /**
> > * pm_runtime_release_supplier - Drop references to device link's supplier.
> > * @link: Target device link.
> > @@ -348,6 +364,7 @@ static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
> > if (!device_link_test(link, DL_FLAG_PM_RUNTIME))
> > continue;
> >
> > + rpm_propagate_last_busy(dev, link->supplier);
> > pm_runtime_release_supplier(link);
> > if (try_to_suspend)
> > pm_request_idle(link->supplier);
> > @@ -710,6 +727,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
> >
> > if (dev->parent) {
> > parent = dev->parent;
> > + if (!parent->power.ignore_children)
> > + rpm_propagate_last_busy(dev, parent);
> > atomic_add_unless(&parent->power.child_count, -1, 0);
> > }
> > wake_up_all(&dev->power.wait_queue);
> > @@ -1368,8 +1387,10 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
> > goto out_set;
> >
> > if (status == RPM_SUSPENDED) {
> > - atomic_add_unless(&parent->power.child_count, -1, 0);
> > notify_parent = !parent->power.ignore_children;
> > + if (notify_parent)
> > + rpm_propagate_last_busy(dev, parent);
> > + atomic_add_unless(&parent->power.child_count, -1, 0);
> > } else {
> > spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);
> >
>
next prev parent reply other threads:[~2026-11-04 0:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 22:14 [PATCH v2 0/5] PM: runtime: Improve autosuspend child to parent propagation Brian Norris
2026-11-03 22:14 ` [PATCH v2 1/5] PM: runtime: Only queue an idle check for RPM-linked suppliers (part 2) Brian Norris
2026-11-03 22:14 ` [PATCH v2 2/5] PM: runtime: Convert last_busy to atomic64_t Brian Norris
2026-11-03 22:14 ` [PATCH v2 3/5] PM: runtime: Propagate last_busy from dependent to dependency Brian Norris
2026-11-03 23:17 ` Jonathan Cameron
2026-11-04 0:32 ` Brian Norris [this message]
2026-11-04 1:40 ` Jonathan Cameron
2026-11-03 22:14 ` [PATCH v2 4/5] PM: runtime: Add tests for last_busy propagation Brian Norris
2026-11-03 23:21 ` Jonathan Cameron
2026-11-03 22:14 ` [PATCH v2 5/5] iio: adc: stm32-adc: Drop runtime_idle() Brian Norris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aup9LKewaLr2B5cR@google.com \
--to=briannorris@chromium.org \
--cc=alexandre.torgue@foss.st.com \
--cc=andy@kernel.org \
--cc=dlechner@baylibre.com \
--cc=fabrice.gasnier@st.com \
--cc=jic23@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mcoquelin.stm32@gmail.com \
--cc=nuno.sa@analog.com \
--cc=rafael@kernel.org \
--cc=ulfh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®