mbox series

[PATCHv2,0/3] PM operations for software nodes

Message ID 20201029105941.63410-1-heikki.krogerus@linux.intel.com
Headers show
Series PM operations for software nodes | expand

Message

Heikki Krogerus Oct. 29, 2020, 10:59 a.m. UTC
Hi,

This is the second version of this series. Rafael pointed out in v1
that I was not handling bus PM ops correctly. He also requested that I
put a comment to the code explaining things a little.

The original v1 series:
https://lore.kernel.org/linux-acpi/20200825135951.53340-1-heikki.krogerus@linux.intel.com/

Heikki Krogerus (3):
  software node: Power management operations for software nodes
  software node: Introduce device_add_software_node()
  usb: dwc3: pci: Register a software node for the dwc3 platform device

 drivers/base/power/common.c |   8 +-
 drivers/base/swnode.c       | 738 +++++++++++++++++++++++++++++++++++-
 drivers/usb/dwc3/dwc3-pci.c | 175 +++++----
 include/linux/property.h    |  13 +
 4 files changed, 835 insertions(+), 99 deletions(-)

Comments

Heikki Krogerus Oct. 29, 2020, 11:51 a.m. UTC | #1
On Thu, Oct 29, 2020 at 01:13:03PM +0200, Sakari Ailus wrote:
> These functions are doing pretty much the same thing but with different

> parameters. How about implementing a macro or a few, which would take all

> the parameters as arguments and return the function to call? A few variants

> may be needed. Individual functions performing different tasks would become

> very simple.


I would prefer to do that as the second step, if you guys don't mind.
I think this was already talked about, but maybe only internally.
Those macros should then be used also in other places where the same
steps are being executed, for example in drivers/base/power/domain.c.

thanks,

-- 
heikki
Andy Shevchenko Oct. 29, 2020, 12:17 p.m. UTC | #2
On Thu, Oct 29, 2020 at 01:51:13PM +0200, Heikki Krogerus wrote:
> On Thu, Oct 29, 2020 at 01:13:03PM +0200, Sakari Ailus wrote:
> > These functions are doing pretty much the same thing but with different
> > parameters. How about implementing a macro or a few, which would take all
> > the parameters as arguments and return the function to call? A few variants
> > may be needed. Individual functions performing different tasks would become
> > very simple.
> 
> I would prefer to do that as the second step, if you guys don't mind.
> I think this was already talked about, but maybe only internally.
> Those macros should then be used also in other places where the same
> steps are being executed, for example in drivers/base/power/domain.c.

I agree.
Sakari Ailus Oct. 29, 2020, 1:01 p.m. UTC | #3
On Thu, Oct 29, 2020 at 01:51:13PM +0200, Heikki Krogerus wrote:
> On Thu, Oct 29, 2020 at 01:13:03PM +0200, Sakari Ailus wrote:

> > These functions are doing pretty much the same thing but with different

> > parameters. How about implementing a macro or a few, which would take all

> > the parameters as arguments and return the function to call? A few variants

> > may be needed. Individual functions performing different tasks would become

> > very simple.

> 

> I would prefer to do that as the second step, if you guys don't mind.

> I think this was already talked about, but maybe only internally.

> Those macros should then be used also in other places where the same

> steps are being executed, for example in drivers/base/power/domain.c.


Works for me.

For the set:

Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>


-- 
Sakari Ailus
Rafael J. Wysocki Oct. 29, 2020, 5:10 p.m. UTC | #4
On Thu, Oct 29, 2020 at 11:59 AM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>

> The software node specific PM operations make it possible to

> handle most PM related quirks separately in their own

> functions instead of conditionally in the device driver's

> generic PM functions (and in some cases all over the

> driver). The software node specific PM operations will also

> reduce the need to pass platform data in some cases, for

> example from a core MFD driver to the child device drivers,

> as from now on the core MFD driver will be able to implement

> the PM quirks directly for the child devices without the

> need to touch the drivers of those child devices.

>

> If a software node includes the PM operations, those PM

> operations are always executed separately on top of the

> other PM operations of the device, so the software node will

> never replace any of the "normal" PM operations of the

> device (including the PM domain's operations, class's or

> bus's PM operations, the device drivers own operations, or

> any other).

>

> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---

>  drivers/base/power/common.c |   8 +-

>  drivers/base/swnode.c       | 693 +++++++++++++++++++++++++++++++++++-

>  include/linux/property.h    |  10 +

>  3 files changed, 701 insertions(+), 10 deletions(-)

>

> diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c

> index bbddb267c2e69..b64cd4690ac63 100644

> --- a/drivers/base/power/common.c

> +++ b/drivers/base/power/common.c

> @@ -109,8 +109,14 @@ int dev_pm_domain_attach(struct device *dev, bool power_on)

>         ret = acpi_dev_pm_attach(dev, power_on);

>         if (!ret)

>                 ret = genpd_dev_pm_attach(dev);

> +       if (ret < 0)

> +               return ret;

>

> -       return ret < 0 ? ret : 0;

> +       ret = software_node_dev_pm_attach(dev, power_on);

> +       if (ret)

> +               dev_pm_domain_detach(dev, power_on);

> +

> +       return ret;

>  }

>  EXPORT_SYMBOL_GPL(dev_pm_domain_attach);

>

> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c

> index 010828fc785bc..595a9c240fede 100644

> --- a/drivers/base/swnode.c

> +++ b/drivers/base/swnode.c

> @@ -8,6 +8,8 @@

>

>  #include <linux/device.h>

>  #include <linux/kernel.h>

> +#include <linux/pm_domain.h>

> +#include <linux/pm_runtime.h>

>  #include <linux/property.h>

>  #include <linux/slab.h>

>

> @@ -48,6 +50,19 @@ EXPORT_SYMBOL_GPL(is_software_node);

>                                      struct swnode, fwnode) : NULL;     \

>         })

>

> +static inline struct swnode *dev_to_swnode(struct device *dev)

> +{

> +       struct fwnode_handle *fwnode = dev_fwnode(dev);

> +

> +       if (!fwnode)

> +               return NULL;

> +

> +       if (!is_software_node(fwnode))

> +               fwnode = fwnode->secondary;

> +

> +       return to_swnode(fwnode);

> +}

> +

>  static struct swnode *

>  software_node_to_swnode(const struct software_node *node)

>  {

> @@ -344,6 +359,673 @@ void property_entries_free(const struct property_entry *properties)

>  }

>  EXPORT_SYMBOL_GPL(property_entries_free);

>

> +/* -------------------------------------------------------------------------- */

> +/* Power management operations */

> +

> +/*

> + * The power management operations in software nodes are handled with a power

> + * management domain - a "wrapper" PM domain:

> + *

> + *   When PM operations are supplied as part of the software node, the primary

> + *   PM domain of the device is stored and replaced with a device specific

> + *   software node PM domain. The software node PM domain's PM operations, which

> + *   are implemented below, will then always call the matching PM operation of

> + *   the primary PM domain (which was stored) on top of the software node's own

> + *   operation.

> + *

> + * If the device does not have primary PM domain, the software node PM wrapper

> + * operations below will also call the classes, buses and device type's PM

> + * operations, and of course the device driver's own PM operations if they are

> + * implemented. The priority of those calls follows drivers/base/power/domain.c:

> + *

> + * 1) device type

> + * 2) class

> + * 3) bus

> + * 4) driver

> + *

> + * NOTE. The software node PM operation is always called before the primary

> + * PM domain with resume/on callbacks, and after the primary PM domain with

> + * suspend/off callbacks. This order is used because the software node PM

> + * operations are primarily meant to be used to implement quirks, quirks that

> + * may be needed to power on the device to a point where it is even possible to

> + * execute the primary PM domain's resume/on routines.

> + */


Well, this basically implements a wrapper PM domain that is somewhat
more generic, as a concept, then software nodes PM.

At least it is not specific to software nodes, so I'd prefer it to be
defined generically.

Moreover, IIUC, this breaks if the "primary" PM domain callbacks try
to get to the original PM domain via the dev->pm_domain pointer, which
the genpd callbacks do.

Do we want to wrap the ACPI PM domain only, by any chance?  If so, it
may be more straightforward to invoke swnode callbacks directly from
there, if any.
Heikki Krogerus Oct. 30, 2020, 10:27 a.m. UTC | #5
Hi Rafael,

On Thu, Oct 29, 2020 at 06:10:59PM +0100, Rafael J. Wysocki wrote:
> Well, this basically implements a wrapper PM domain that is somewhat

> more generic, as a concept, then software nodes PM.

> 

> At least it is not specific to software nodes, so I'd prefer it to be

> defined generically.


I don't think we should generalize it like that. I do not think the
power domains should have any links between each other at the general
level (just like we probable should not link fwnodes together anymore
like we do now with the "secondary" fwnode). That is why I have
confined this to software nodes only for now.

I think ideally devices could belong to multiple power domains. That
would be the general solution. I did not think that trying to figure
out how to do that would be reasonable as the first approach (maybe I
should have done exactly that?). But would it be acceptable to allow
devices to belong to multiple power domains?

> Moreover, IIUC, this breaks if the "primary" PM domain callbacks try

> to get to the original PM domain via the dev->pm_domain pointer, which

> the genpd callbacks do.


Ouch, that is true.

> Do we want to wrap the ACPI PM domain only, by any chance?  If so, it

> may be more straightforward to invoke swnode callbacks directly from

> there, if any.


The software node can still be the only "primary" fwnode. I don't
think we should limit this to only platforms (and kernels) that
support ACPI.


thanks,

-- 
heikki