Re: [PATCH v1 3/3] PM: sleep: Use DPM_FLAG_SMART_SUSPEND conditionally

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 18, 2025 at 1:49 PM Ulf Hansson <ulf.hansson@xxxxxxxxxx> wrote:
>
> + Saravana
>
> On Mon, 17 Feb 2025 at 21:19, Rafael J. Wysocki <rjw@xxxxxxxxxxxxx> wrote:
> >
> > From: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
> >
> > A recent discussion has revealed that using DPM_FLAG_SMART_SUSPEND
> > unconditionally is generally problematic because it may lead to
> > situations in which the device's runtime PM information is internally
> > inconsistent or does not reflect its real state [1].
> >
> > For this reason, change the handling of DPM_FLAG_SMART_SUSPEND so that
> > it is only taken into account if it is consistently set by the drivers
> > of all devices having any PM callbacks throughout dependency graphs in
> > accordance with the following rules:
> >
> >  - The "smart suspend" feature is only enabled for devices whose drivers
> >    ask for it (that is, set DPM_FLAG_SMART_SUSPEND) and for devices
> >    without PM callbacks unless they have never had runtime PM enabled.
> >
> >  - The "smart suspend" feature is not enabled for a device if it has not
> >    been enabled for the device's parent unless the parent does not take
> >    children into account or it has never had runtime PM enabled.
> >
> >  - The "smart suspend" feature is not enabled for a device if it has not
> >    been enabled for one of the device's suppliers taking runtime PM into
> >    account unless that supplier has never had runtime PM enabled.
> >
> > Namely, introduce a new device PM flag called smart_suspend that is only
> > set if the above conditions are met and update all DPM_FLAG_SMART_SUSPEND
> > users to check power.smart_suspend instead of directly checking the
> > latter.
> >
> > At the same time, drop the power.set_active flage introduced recently
> > in commit 3775fc538f53 ("PM: sleep: core: Synchronize runtime PM status
> > of parents and children") because it is now sufficient to check
> > power.smart_suspend along with the dev_pm_skip_resume() return value
> > to decide whether or not pm_runtime_set_active() needs to be called
> > for the device.
> >
> > Link: https://lore.kernel.org/linux-pm/CAPDyKFroyU3YDSfw_Y6k3giVfajg3NQGwNWeteJWqpW29BojhQ@xxxxxxxxxxxxxx/  [1]
> > Fixes: 7585946243d6 ("PM: sleep: core: Restrict power.set_active propagation")
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
> > ---
> >  drivers/acpi/device_pm.c  |    6 +---
> >  drivers/base/power/main.c |   63 +++++++++++++++++++++++++++++++++++-----------
> >  drivers/mfd/intel-lpss.c  |    2 -
> >  drivers/pci/pci-driver.c  |    6 +---
> >  include/linux/pm.h        |    2 -
> >  5 files changed, 55 insertions(+), 24 deletions(-)
> >
> > --- a/drivers/acpi/device_pm.c
> > +++ b/drivers/acpi/device_pm.c
> > @@ -1161,8 +1161,7 @@
> >   */
> >  int acpi_subsys_suspend(struct device *dev)
> >  {
> > -       if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
> > -           acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
> > +       if (!dev->power.smart_suspend || acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
>
> Nitpick: Rather than checking the dev->power.smart_suspend flag
> directly here, perhaps we should provide a helper function that
> returns true when dev->power.smart_suspend is set? In this way, it's
> the PM core soley that operates on the flag.

I can add a wrapper around this, sure.

> >                 pm_runtime_resume(dev);
> >
> >         return pm_generic_suspend(dev);
> > @@ -1320,8 +1319,7 @@
> >   */
> >  int acpi_subsys_poweroff(struct device *dev)
> >  {
> > -       if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
> > -           acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
> > +       if (!dev->power.smart_suspend || acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
> >                 pm_runtime_resume(dev);
> >
> >         return pm_generic_poweroff(dev);
> > --- a/drivers/base/power/main.c
> > +++ b/drivers/base/power/main.c
> > @@ -656,15 +656,13 @@
> >          * so change its status accordingly.
> >          *
> >          * Otherwise, the device is going to be resumed, so set its PM-runtime
> > -        * status to "active" unless its power.set_active flag is clear, in
> > +        * status to "active" unless its power.smart_suspend 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->power.set_active) {
> > +       else if (dev->power.smart_suspend)
> >                 pm_runtime_set_active(dev);
> > -               dev->power.set_active = false;
> > -       }
> >
> >         if (dev->pm_domain) {
> >                 info = "noirq power domain ";
> > @@ -1282,14 +1280,8 @@
> >               dev->power.may_skip_resume))
> >                 dev->power.must_resume = true;
> >
> > -       if (dev->power.must_resume) {
> > -               if (dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) {
> > -                       dev->power.set_active = true;
> > -                       if (dev->parent && !dev->parent->power.ignore_children)
> > -                               dev->parent->power.set_active = true;
> > -               }
> > +       if (dev->power.must_resume)
> >                 dpm_superior_set_must_resume(dev);
> > -       }
> >
> >  Complete:
> >         complete_all(&dev->power.completion);
> > @@ -1797,6 +1789,49 @@
> >         return error;
> >  }
> >
> > +static void device_prepare_smart_suspend(struct device *dev)
> > +{
> > +       struct device_link *link;
> > +       int idx;
> > +
> > +       /*
> > +        * The "smart suspend" feature is enabled for devices whose drivers ask
> > +        * for it and for devices without PM callbacks unless runtime PM is
> > +        * disabled and enabling it is blocked for them.
> > +        *
> > +        * However, if "smart suspend" is not enabled for the device's parent
> > +        * or any of its suppliers that take runtime PM into account, it cannot
> > +        * be enabled for the device either.
> > +        */
> > +       dev->power.smart_suspend = (dev->power.no_pm_callbacks ||
> > +               dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) &&
> > +               !pm_runtime_blocked(dev);
> > +
> > +       if (!dev->power.smart_suspend)
> > +               return;
> > +
> > +       if (dev->parent && !pm_runtime_blocked(dev->parent) &&
> > +           !dev->parent->power.ignore_children && !dev->parent->power.smart_suspend) {
> > +               dev->power.smart_suspend = false;
> > +               return;
> > +       }
> > +
> > +       idx = device_links_read_lock();
> > +
> > +       list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) {
> > +               if (!(link->flags | DL_FLAG_PM_RUNTIME))
> > +                       continue;
> > +
> > +               if (!pm_runtime_blocked(link->supplier) &&
> > +                   !link->supplier->power.smart_suspend) {
>
> This requires device_prepare() for all suppliers to be run before its
> consumer. Is that always the case?

Yes, it is by design.

> > +                       dev->power.smart_suspend = false;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       device_links_read_unlock(idx);
>
> From an execution overhead point of view, did you check if the above
> code had some measurable impact on the latency for dpm_prepare()?

It didn't on my systems.

For the vast majority of devices the overhead is just checking
power.no_pm_callbacks and DPM_FLAG_SMART_SUSPEND.  For some,
pm_runtime_blocked() needs to be called which requires grabbing a
spinlock and there are only a few with power.smart_suspend set to
start with.

I'm wondering why you didn't have this concern regarding other changes
that involved walking suppliers or consumers, though.





[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux