Linux-ACPI Archive on lore.kernel.org
 help / color / Atom feed
From: "Rafael J. Wysocki" <rafael@kernel.org>
To: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Bjorn Helgaas <bhelgaas@google.com>, Len Brown <lenb@kernel.org>,
	Lukas Wunner <lukas@wunner.de>,
	Keith Busch <keith.busch@intel.com>,
	Alex Williamson <alex.williamson@redhat.com>,
	Alexandru Gagniuc <mr.nuke.me@gmail.com>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>
Subject: Re: [PATCH v2 2/3] ACPI / PM: Introduce concept of a _PR0 dependent device
Date: Wed, 19 Jun 2019 15:20:45 +0200
Message-ID: <CAJZ5v0jaNpgW2=QfTVYcY=2MzTCaxNNSsVT667Lwz8HxvJT8mQ@mail.gmail.com> (raw)
In-Reply-To: <20190618161858.77834-3-mika.westerberg@linux.intel.com>

On Tue, Jun 18, 2019 at 6:19 PM Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
>
> If there are shared power resources between otherwise unrelated devices
> turning them on causes the other devices sharing them to be powered up
> as well. In case of PCI devices go into D0uninitialized state meaning
> that if they were configured to trigger wake that configuration is lost
> at this point.
>
> For this reason introduce a concept of "_PR0 dependent device" that can
> be added to any ACPI device that has power resources. The dependent
> device will be included in a list of dependent devices for all power
> resources returned by the ACPI device's _PR0 (assuming it has one).
> Whenever a power resource having dependent devices is turned physically
> on (its _ON method is called) we runtime resume all of them to allow
> their driver or in case of PCI the PCI core to re-initialize the device
> and its wake configuration.
>
> This adds two functions that can be used to add and remove these
> dependent devices. Note the dependent device does not necessary need
> share power resources so this functionality can be used to add "software
> dependencies" as well if needed.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/acpi/power.c    | 139 ++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acpi_bus.h |   4 ++
>  2 files changed, 143 insertions(+)
>
> diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
> index a916417b9e70..76d298192940 100644
> --- a/drivers/acpi/power.c
> +++ b/drivers/acpi/power.c
> @@ -42,6 +42,11 @@ ACPI_MODULE_NAME("power");
>  #define ACPI_POWER_RESOURCE_STATE_ON   0x01
>  #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
>
> +struct acpi_power_dependent_device {
> +       struct device *dev;
> +       struct list_head node;
> +};
> +
>  struct acpi_power_resource {
>         struct acpi_device device;
>         struct list_head list_node;
> @@ -51,6 +56,7 @@ struct acpi_power_resource {
>         unsigned int ref_count;
>         bool wakeup_enabled;
>         struct mutex resource_lock;
> +       struct list_head dependents;
>  };
>
>  struct acpi_power_resource_entry {
> @@ -232,8 +238,125 @@ static int acpi_power_get_list_state(struct list_head *list, int *state)
>         return 0;
>  }
>
> +static int
> +acpi_power_resource_add_dependent(struct acpi_power_resource *resource,
> +                                 struct device *dev)
> +{
> +       struct acpi_power_dependent_device *dep;
> +       int ret = 0;
> +
> +       mutex_lock(&resource->resource_lock);
> +       list_for_each_entry(dep, &resource->dependents, node) {
> +               /* Only add it once */
> +               if (dep->dev == dev)
> +                       goto unlock;
> +       }
> +
> +       dep = kzalloc(sizeof(*dep), GFP_KERNEL);
> +       if (!dep) {
> +               ret = -ENOMEM;
> +               goto unlock;
> +       }
> +
> +       dep->dev = dev;
> +       list_add_tail(&dep->node, &resource->dependents);
> +       dev_dbg(dev, "added power dependency to [%s]\n", resource->name);
> +
> +unlock:
> +       mutex_unlock(&resource->resource_lock);
> +       return ret;
> +}
> +
> +static void
> +acpi_power_resource_remove_dependent(struct acpi_power_resource *resource,
> +                                    struct device *dev)
> +{
> +       struct acpi_power_dependent_device *dep;
> +
> +       mutex_lock(&resource->resource_lock);
> +       list_for_each_entry(dep, &resource->dependents, node) {
> +               if (dep->dev == dev) {
> +                       list_del(&dep->node);
> +                       kfree(dep);
> +                       dev_dbg(dev, "removed power dependency to [%s]\n",
> +                               resource->name);
> +                       break;
> +               }
> +       }
> +       mutex_unlock(&resource->resource_lock);
> +}
> +
> +/**
> + * acpi_device_power_add_dependent - Add dependent device of this ACPI device
> + * @adev: ACPI device pointer
> + * @dev: Dependent device
> + *
> + * If @adev has non-empty _PR0 the @dev is added as dependent device to all
> + * power resources returned by it. This means that whenever these power
> + * resources are turned _ON the dependent devices get runtime resumed. This
> + * is needed for devices such as PCI to allow its driver to re-initialize
> + * it after it went to D0uninitialized.
> + *
> + * If @adev does not have _PR0 this does nothing.
> + *
> + * Returns %0 in case of success and negative errno otherwise.
> + */
> +int acpi_device_power_add_dependent(struct acpi_device *adev,
> +                                   struct device *dev)
> +{
> +       struct acpi_power_resource_entry *entry;
> +       struct list_head *resources;
> +       int ret;
> +
> +       if (!adev->power.flags.power_resources)
> +               return 0;
> +       if (!adev->power.states[ACPI_STATE_D0].flags.valid)
> +               return 0;

The two checks above can be replaced with an
adev->flags.power_manageable one AFAICS (the "valid" flag is always
set for D0 and the list below will be empty if there are no power
resources).

Same for acpi_device_power_remove_dependent(), of course.

Apart from this LGTM.

  reply index

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-18 16:18 [PATCH v2 0/3] PCI / ACPI: Handle sibling devices sharing power resources Mika Westerberg
2019-06-18 16:18 ` [PATCH v2 1/3] PCI / ACPI: Use cached ACPI device state to get PCI device power state Mika Westerberg
2019-06-19 21:28   ` Bjorn Helgaas
2019-06-20  8:27     ` Mika Westerberg
2019-06-20 13:16       ` Bjorn Helgaas
2019-06-20 13:37         ` Mika Westerberg
2019-06-20 14:15           ` Bjorn Helgaas
2019-06-21 10:32             ` Rafael J. Wysocki
2019-06-21 13:09               ` Bjorn Helgaas
2019-06-22  8:51                 ` Rafael J. Wysocki
2019-06-24 10:57                   ` Mika Westerberg
2019-06-24 11:14               ` Rafael J. Wysocki
2019-06-25  9:45                 ` Mika Westerberg
2019-06-25 10:00                   ` Rafael J. Wysocki
2019-06-25 10:08                     ` Mika Westerberg
2019-06-21 11:56   ` Rafael J. Wysocki
2019-06-24 10:58     ` Mika Westerberg
2019-06-18 16:18 ` [PATCH v2 2/3] ACPI / PM: Introduce concept of a _PR0 dependent device Mika Westerberg
2019-06-19 13:20   ` Rafael J. Wysocki [this message]
2019-06-19 13:34     ` Mika Westerberg
2019-06-18 16:18 ` [PATCH v2 3/3] PCI / ACPI: Add _PR0 dependent devices Mika Westerberg
2019-06-19 13:24 ` [PATCH v2 0/3] PCI / ACPI: Handle sibling devices sharing power resources Rafael J. Wysocki

Reply instructions:

You may reply publically 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='CAJZ5v0jaNpgW2=QfTVYcY=2MzTCaxNNSsVT667Lwz8HxvJT8mQ@mail.gmail.com' \
    --to=rafael@kernel.org \
    --cc=alex.williamson@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=keith.busch@intel.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=mika.westerberg@linux.intel.com \
    --cc=mr.nuke.me@gmail.com \
    --cc=rjw@rjwysocki.net \
    /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

Linux-ACPI Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-acpi/0 linux-acpi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-acpi linux-acpi/ https://lore.kernel.org/linux-acpi \
		linux-acpi@vger.kernel.org linux-acpi@archiver.kernel.org
	public-inbox-index linux-acpi


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-acpi


AGPL code for this site: git clone https://public-inbox.org/ public-inbox