Re: [PATCH v1] PM: sleep: core: Synchronize runtime PM status of parents and children

Ulf Hansson
2025-01-29T16:42:41Z

On Wed, 29 Jan 2025 at 16:55, Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Wed, Jan 29, 2025 at 12:53 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > On Tue, 28 Jan 2025 at 20:24, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > >
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > Commit 6e176bf8d461 ("PM: sleep: core: Do not skip callbacks in the
> > > resume phase") overlooked the case in which the parent of a device with
> > > DPM_FLAG_SMART_SUSPEND set did not use that flag and could be runtime-
> > > suspended before a transition into a system-wide sleep state. In that
> > > case, if the child is resumed during the subsequent transition from
> > > that state into the working state, its runtime PM status will be set to
> > > RPM_ACTIVE, but the runtime PM status of the parent will not be updated
> > > accordingly, even though the parent will be resumed too, because of the
> > > dev_pm_skip_suspend() check in device_resume_noirq().
> > >
> > > Address this problem by tracking the need to set the runtime PM status
> > > to RPM_ACTIVE during system-wide resume transitions for devices with
> > > DPM_FLAG_SMART_SUSPEND set and all of the devices depended on by them.
> > >
> > > Fixes: 6e176bf8d461 ("PM: sleep: core: Do not skip callbacks in the resume phase")
> > > Closes: https://lore.kernel.org/linux-pm/Z30p2Etwf3F2AUvD@hovoldconsulting.com/
> > > Reported-by: Johan Hovold <johan@kernel.org>
> > > Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > > drivers/base/power/main.c | 29 ++++++++++++++++++++---------
> > > include/linux/pm.h | 1 +
> > > 2 files changed, 21 insertions(+), 9 deletions(-)
> > >
> > > --- a/drivers/base/power/main.c
> > > +++ b/drivers/base/power/main.c
> > > @@ -656,13 +656,15 @@
> > > * so change its status accordingly.
> > > *
> > > * Otherwise, the device is going to be resumed, so set its PM-runtime
> > > - * status to "active", but do that only if DPM_FLAG_SMART_SUSPEND is set
> > > - * to avoid confusing drivers that don't use it.
> > > + * status to "active" unless its power.set_active flag is clear, in
> > > + * which case it is not necessary to update its PM-runtime status.
> > > */
> > > - if (skip_resume)
> > > + if (skip_resume) {
> > > pm_runtime_set_suspended(dev);
> > > - else if (dev_pm_skip_suspend(dev))
> > > + } else if (dev->power.set_active) {
> > > pm_runtime_set_active(dev);
> > > + dev->power.set_active = false;
> > > + }
> > >
> > > if (dev->pm_domain) {
> > > info = "noirq power domain ";
> > > @@ -1189,18 +1191,24 @@
> > > return PMSG_ON;
> > > }
> > >
> > > -static void dpm_superior_set_must_resume(struct device *dev)
> > > +static void dpm_superior_set_must_resume(struct device *dev, bool set_active)
> > > {
> > > struct device_link *link;
> > > int idx;
> > >
> > > - if (dev->parent)
> > > + if (dev->parent) {
> > > dev->parent->power.must_resume = true;
> > > + if (set_active)
> > > + dev->parent->power.set_active = true;
> > > + }
> > >
> > > idx = device_links_read_lock();
> > >
> > > - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node)
> > > + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) {
> > > link->supplier->power.must_resume = true;
> > > + if (set_active)
> > > + link->supplier->power.set_active = true;
> >
> > If I understand correctly, the suppliers are already handled when the
> > pm_runtime_set_active() is called for consumers, so the above should
> > not be needed.
>
> It is needed because pm_runtime_set_active() doesn't cause the setting
> to propagate to the parent's/suppliers of the suppliers AFAICS.

Hmm, even if that sounds reasonable, I don't think it's a good idea as
it may introduce interesting propagation problems between drivers.

For example, consider that Saravana is trying to enable runtime PM for
fw_devlinks. It would mean synchronization issues for the runtime PM
status, all over the place.

That said, is even consumer/suppliers part of the problem we are
trying to solve?

>
> > That said, maybe we instead allow parent/child to work in the similar
> > way as for consumer/suppliers, when pm_runtime_set_active() is called
> > for the child. In other words, when pm_runtime_set_active() is called
> > for a child and the parent is runtime PM enabled, let's runtime resume
> > it too, as we do for suppliers. Would that work, you think?
>
> The parent is not runtime-PM enabled when this happens.

That sounds really weird to me.

Does that mean that the parent has not been system resumed either? If
so, isn't that really the root cause for this problem, or what am I
missing?

Kind regards
Uffe