All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <bhelgaas@google.com>
To: Aaron Lu <aaron.lu@intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
	ACPI Devel Mailing List <linux-acpi@vger.kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>
Subject: Re: [PATCH 2/2] PCI / ACPI: PCI delay optimization from ACPI
Date: Mon, 23 Mar 2015 10:09:55 -0500	[thread overview]
Message-ID: <20150323150955.GR26935@google.com> (raw)
In-Reply-To: <550FDA38.2090505@intel.com>

On Mon, Mar 23, 2015 at 05:17:44PM +0800, Aaron Lu wrote:
> An ECN meant to specify possible delay optimizations is available on
> the PCI website:
> https://www.pcisig.com/specifications/conventional/pci_firmware/ECN_fw_latency_optimization_final.pdf
> where it has defined two functions for an UUID specified _DSM:
> Function 8: If system firmware assumes the responsibility of post
> Conventional Reset delay (and informs the Operating System via this DSM
> function) on Sx Resume (such as boot from ACPI S5, or resume from ACPI
> S4 or S3 states), the Operating System may assume sufficient time has
> elapsed since the end of reset, and devices within the PCI subsystem are
> ready for Configuration Access.
> If the system firmware supports runtime power gating on any of the
> device within PCI subsystem covered by this DSM function, the system
> firmware is responsible for covering the necessary post power-on reset
> delay.
> 
> Function 9: Specify various smaller delay values than required by the
> SPEC for individual PCI devices like shorter delay values after
> conventional reset, D3hot to D0 transition, functional level reset, etc.
> 
> This patche adds support for function 8 and part of function 9. For
> function 8, the patch will check if the required _DSM function satisfies
> the requirement and then set the per PCI device's d3cold_delay variable
> to zero. For function 9, the values affecting delays after conventional
> reset and D3hot->D0 are examined and the per PCI device's d3cold_delay
> and d3_delay are updated if the _DSM's return value is smaller than what
> the SPEC requires.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> ---
>  drivers/pci/pci-acpi.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pci.h      |  2 ++
>  2 files changed, 65 insertions(+)
> 
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 6ef2019073e2..2ebd02d814d7 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -563,6 +563,66 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
>  				      check_children);
>  }
>  
> +/**
> + * pci_acpi_delay_optimize - optimize PCI D3 and D3cold delay from ACPI
> + * @pdev: the PCI device whose delay is to be updated
> + * @adev: the companion ACPI device of this PCI device
> + *
> + * Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
> + * control method of either its own or its parent bridge.
> + *
> + * The UUID of the _DSM control method, together with other information like
> + * which delay values can be optimized, etc. is defined in a ECN available on
> + * PCIsig.com titled as: ACPI additions for FW latency optimizations.
> + * Function 9 of the ACPI _DSM control method, if available for a specific PCI
> + * device, provides various possible delay values that are less than what the
> + * SPEC requires. Here, we only deal with d3_delay and d3cold_delay. Others
> + * can be added later.
> + * Function 8 of the ACPI _DSM control method, if available for the PCI host
> + * bridge, means all its children devices do not need the reset delay when
> + * leaving from D3cold state.
> + */
> +static void pci_acpi_delay_optimize(struct pci_dev *pdev,
> +				    struct acpi_device *adev)
> +{
> +	acpi_handle handle = adev->handle;
> +	int value;
> +	union acpi_object *obj, *elements;
> +
> +	obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
> +				FUNCTION_DELAY_DSM, NULL);
> +	if (obj) {
> +		if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 5) {
> +			elements = obj->package.elements;
> +			if (elements[0].type == ACPI_TYPE_INTEGER) {
> +				value = (int)elements[0].integer.value / 1000;
> +				if (value < PCI_PM_D3COLD_WAIT)
> +					pdev->d3cold_delay = value;
> +			}
> +			if (elements[3].type == ACPI_TYPE_INTEGER) {
> +				value = (int)elements[3].integer.value / 1000;
> +				if (value < PCI_PM_D3_WAIT)
> +					pdev->d3_delay = value;
> +			}
> +		}
> +		kfree(obj);
> +	}
> +
> +	/* Function 8 is only applicable to host bridge */
> +	if (pdev->bus->bridge->parent)
> +		return;
> +
> +	handle = ACPI_HANDLE(pdev->bus->bridge);
> +	obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
> +				RESET_DELAY_DSM, NULL);

The ECN says this function is in a host bridge scope and applies to the
PCI subsystem beneath the bridge.  This code does not map well to that
because:

  1) It evaluates _DSM more times than necessary (we only need to do it
  once per host bridge, and this does it once for every PCI device
  immediately below a host brige).

  2) The settings are only applied to immediate children of the host
  bridge, not to devices deeper in the hierarchy.

  3) A reader of the ECN will expect the corresponding code to be in the
  host bridge driver (pci_root.c) where we deal with other host bridge
  properties, not in per-PCI device code like this.

  4) The ECN is not explicit about this, but if both function 8 (which
  applies to a whole hierarchy) and function 9 (which applies to a single
  PCI device) are implemented for the same PCI device, I would expect
  function 9 to take precedence over function 8.  This patch does the
  reverse, since function 8 will overwrite any d3cold_delay that was set
  above by function 9.

> +	if (!obj)
> +		return;
> +
> +	if (obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 1)
> +		pdev->d3cold_delay = 0;
> +	kfree(obj);
> +}
> +
>  static void pci_acpi_setup(struct device *dev)
>  {
>  	struct pci_dev *pci_dev = to_pci_dev(dev);
> @@ -571,6 +631,9 @@ static void pci_acpi_setup(struct device *dev)
>  	if (!adev)
>  		return;
>  
> +	if (pci_dev->pm_cap)
> +		pci_acpi_delay_optimize(pci_dev, adev);
> +
>  	pci_acpi_add_pm_notifier(adev, pci_dev);
>  	if (!adev->wakeup.flags.valid)
>  		return;
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index c901ab84cf3b..3eaefac5acc5 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -325,6 +325,8 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
>  extern const u8 pci_acpi_dsm_uuid[];
>  
>  #define DEVICE_LABEL_DSM	0x07
> +#define RESET_DELAY_DSM		0x08
> +#define FUNCTION_DELAY_DSM	0x09
>  #endif
>  
>  #endif /* DRIVERS_PCI_H */
> -- 
> 2.1.0
> 

  reply	other threads:[~2015-03-23 15:09 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-09  7:46 [PATCH] PCI / ACPI: PCI delay optimization from ACPI Aaron Lu
2015-03-09 14:33 ` Rafael J. Wysocki
2015-03-10  6:47   ` Aaron Lu
2015-03-10  6:48   ` [PATCH update] " Aaron Lu
2015-03-20  6:14     ` Aaron Lu
2015-03-20 12:39       ` Rafael J. Wysocki
2015-03-20 21:03     ` Bjorn Helgaas
2015-03-23  5:35       ` Aaron Lu
2015-03-23  9:15         ` Aaron Lu
2015-03-23  9:16       ` [PATCH 1/2] PCI: rename dsm uuid for PCI Aaron Lu
2015-03-24  0:24         ` Rafael J. Wysocki
2015-03-24  0:35           ` Aaron Lu
2015-03-24  1:03             ` Rafael J. Wysocki
2015-03-24  9:04               ` [PATCH v2 1/2] PCI: rename _DSM UUID array Aaron Lu
2015-03-24 21:57                 ` Rafael J. Wysocki
2015-03-23  9:17       ` [PATCH 2/2] PCI / ACPI: PCI delay optimization from ACPI Aaron Lu
2015-03-23 15:09         ` Bjorn Helgaas [this message]
2015-03-24  9:04           ` [PATCH v2 " Aaron Lu
2015-03-24 14:08             ` Bjorn Helgaas
2015-03-24 15:16               ` Aaron Lu
2015-03-24 22:09                 ` Bjorn Helgaas
2015-03-24 15:37               ` Aaron Lu
2015-03-24 22:10                 ` Bjorn Helgaas
2015-03-25  6:30 ` [PATCH v3 0/3] " Aaron Lu
2015-03-25  6:31   ` [PATCH v3 1/3] PCI: rename _DSM UUID array Aaron Lu
2015-03-25  6:32   ` [PATCH v3 2/3] PCI: rename find_pci_host_bridge and export it Aaron Lu
2015-03-25  6:37   ` [PATCH v3 3/3] PCI / ACPI: PCI delay optimization from ACPI Aaron Lu
2015-03-29 14:17   ` [PATCH v3 0/3] " Aaron Lu
2015-04-08 21:32   ` Bjorn Helgaas

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=20150323150955.GR26935@google.com \
    --to=bhelgaas@google.com \
    --cc=aaron.lu@intel.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.