linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Linux ACPI <linux-acpi@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Linux PM <linux-pm@vger.kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	Kai-Heng Feng <kai.heng.feng@canonical.com>
Subject: Re: [PATCH v1 1/2] PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
Date: Fri, 4 Dec 2020 17:21:25 -0600	[thread overview]
Message-ID: <20201204232125.GA1981160@bjorn-Precision-5520> (raw)
In-Reply-To: <2261308.G18gbxz5ee@kreacher>

On Tue, Nov 24, 2020 at 08:44:00PM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The idea behind acpi_pm_set_bridge_wakeup() was to allow bridges to
> be reference counted for wakeup enabling, because they may be enabled
> to signal wakeup on behalf of their subordinate devices and that
> may happen for multiple times in a row, whereas for the other devices
> it only makes sense to enable wakeup signaling once.
> 
> However, this becomes problematic if the bridge itself is suspended,
> because it is treated as a "regular" device in that case and the
> reference counting doesn't work.
> 
> For instance, suppose that there are two devices below a bridge and
> they both can signal wakeup.  Every time one of them is suspended,
> wakeup signaling is enabled for the bridge, so when they both have
> been suspended, the bridge's wakeup reference counter value is 2.
> 
> Say that the bridge is suspended subsequently and acpi_pci_wakeup()
> is called for it.  Because the bridge can signal wakeup, that
> function will invoke acpi_pm_set_device_wakeup() to configure it
> and __acpi_pm_set_device_wakeup() will be called with the last
> argument equal to 1.  This causes __acpi_device_wakeup_enable()
> invoked by it to omit the reference counting, because the reference
> counter of the target device (the bridge) is 2 at that time.
> 
> Now say that the bridge resumes and one of the device below it
> resumes too, so the bridge's reference counter becomes 0 and
> wakeup signaling is disabled for it, but there is still the other
> suspended device which may need the bridge to signal wakeup on its
> behalf and that is not going to work.
> 
> To address this scenario, use wakeup enable reference counting for
> all devices, not just for bridges, so drop the last argument from
> __acpi_device_wakeup_enable() and __acpi_pm_set_device_wakeup(),
> which causes acpi_pm_set_device_wakeup() and
> acpi_pm_set_bridge_wakeup() to become identical, so drop the latter
> and use the former instead of it everywhere.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

> ---
>  drivers/acpi/device_pm.c |   41 ++++++++++++-----------------------------
>  drivers/pci/pci-acpi.c   |    4 ++--
>  include/acpi/acpi_bus.h  |    5 -----
>  3 files changed, 14 insertions(+), 36 deletions(-)
> 
> Index: linux-pm/include/acpi/acpi_bus.h
> ===================================================================
> --- linux-pm.orig/include/acpi/acpi_bus.h
> +++ linux-pm/include/acpi/acpi_bus.h
> @@ -620,7 +620,6 @@ acpi_status acpi_remove_pm_notifier(stru
>  bool acpi_pm_device_can_wakeup(struct device *dev);
>  int acpi_pm_device_sleep_state(struct device *, int *, int);
>  int acpi_pm_set_device_wakeup(struct device *dev, bool enable);
> -int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable);
>  #else
>  static inline void acpi_pm_wakeup_event(struct device *dev)
>  {
> @@ -651,10 +650,6 @@ static inline int acpi_pm_set_device_wak
>  {
>  	return -ENODEV;
>  }
> -static inline int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable)
> -{
> -	return -ENODEV;
> -}
>  #endif
>  
>  #ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT
> Index: linux-pm/drivers/acpi/device_pm.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/device_pm.c
> +++ linux-pm/drivers/acpi/device_pm.c
> @@ -749,7 +749,7 @@ static void acpi_pm_notify_work_func(str
>  static DEFINE_MUTEX(acpi_wakeup_lock);
>  
>  static int __acpi_device_wakeup_enable(struct acpi_device *adev,
> -				       u32 target_state, int max_count)
> +				       u32 target_state)
>  {
>  	struct acpi_device_wakeup *wakeup = &adev->wakeup;
>  	acpi_status status;
> @@ -757,9 +757,10 @@ static int __acpi_device_wakeup_enable(s
>  
>  	mutex_lock(&acpi_wakeup_lock);
>  
> -	if (wakeup->enable_count >= max_count)
> +	if (wakeup->enable_count >= INT_MAX) {
> +		acpi_handle_info(adev->handle, "Wakeup enable count out of bounds!\n");
>  		goto out;
> -
> +	}
>  	if (wakeup->enable_count > 0)
>  		goto inc;
>  
> @@ -799,7 +800,7 @@ out:
>   */
>  static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state)
>  {
> -	return __acpi_device_wakeup_enable(adev, target_state, 1);
> +	return __acpi_device_wakeup_enable(adev, target_state);
>  }
>  
>  /**
> @@ -829,8 +830,12 @@ out:
>  	mutex_unlock(&acpi_wakeup_lock);
>  }
>  
> -static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable,
> -				       int max_count)
> +/**
> + * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
> + * @dev: Device to enable/disable to generate wakeup events.
> + * @enable: Whether to enable or disable the wakeup functionality.
> + */
> +int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
>  {
>  	struct acpi_device *adev;
>  	int error;
> @@ -850,37 +855,15 @@ static int __acpi_pm_set_device_wakeup(s
>  		return 0;
>  	}
>  
> -	error = __acpi_device_wakeup_enable(adev, acpi_target_system_state(),
> -					    max_count);
> +	error = __acpi_device_wakeup_enable(adev, acpi_target_system_state());
>  	if (!error)
>  		dev_dbg(dev, "Wakeup enabled by ACPI\n");
>  
>  	return error;
>  }
> -
> -/**
> - * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
> - * @dev: Device to enable/disable to generate wakeup events.
> - * @enable: Whether to enable or disable the wakeup functionality.
> - */
> -int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
> -{
> -	return __acpi_pm_set_device_wakeup(dev, enable, 1);
> -}
>  EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup);
>  
>  /**
> - * acpi_pm_set_bridge_wakeup - Enable/disable remote wakeup for given bridge.
> - * @dev: Bridge device to enable/disable to generate wakeup events.
> - * @enable: Whether to enable or disable the wakeup functionality.
> - */
> -int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable)
> -{
> -	return __acpi_pm_set_device_wakeup(dev, enable, INT_MAX);
> -}
> -EXPORT_SYMBOL_GPL(acpi_pm_set_bridge_wakeup);
> -
> -/**
>   * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
>   * @dev: Device to put into a low-power state.
>   * @adev: ACPI device node corresponding to @dev.
> Index: linux-pm/drivers/pci/pci-acpi.c
> ===================================================================
> --- linux-pm.orig/drivers/pci/pci-acpi.c
> +++ linux-pm/drivers/pci/pci-acpi.c
> @@ -1060,7 +1060,7 @@ static int acpi_pci_propagate_wakeup(str
>  {
>  	while (bus->parent) {
>  		if (acpi_pm_device_can_wakeup(&bus->self->dev))
> -			return acpi_pm_set_bridge_wakeup(&bus->self->dev, enable);
> +			return acpi_pm_set_device_wakeup(&bus->self->dev, enable);
>  
>  		bus = bus->parent;
>  	}
> @@ -1068,7 +1068,7 @@ static int acpi_pci_propagate_wakeup(str
>  	/* We have reached the root bus. */
>  	if (bus->bridge) {
>  		if (acpi_pm_device_can_wakeup(bus->bridge))
> -			return acpi_pm_set_bridge_wakeup(bus->bridge, enable);
> +			return acpi_pm_set_device_wakeup(bus->bridge, enable);
>  	}
>  	return 0;
>  }
> 
> 
> 

  parent reply	other threads:[~2020-12-04 23:22 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-24 19:41 [PATCH v1 0/2] PM: ACPI: PCI: Address issues related to signaling wakeup from bridges Rafael J. Wysocki
2020-11-24 19:44 ` [PATCH v1 1/2] PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup() Rafael J. Wysocki
2020-11-25  8:06   ` Mika Westerberg
2020-12-04 23:21   ` Bjorn Helgaas [this message]
2020-11-24 19:46 ` [PATCH v1 2/2] PM: ACPI: Refresh wakeup device power configuration every time Rafael J. Wysocki
2020-11-25  8:09   ` Mika Westerberg

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=20201204232125.GA1981160@bjorn-Precision-5520 \
    --to=helgaas@kernel.org \
    --cc=kai.heng.feng@canonical.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=rafael@kernel.org \
    --cc=rjw@rjwysocki.net \
    --subject='Re: [PATCH v1 1/2] PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()' \
    /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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).