[PATCH v14.c 3/4] PCI: ACPI: Use device constraints to opt devices into D3 support

From: Mario Limonciello
Date: Fri Aug 18 2023 - 15:41:52 EST


In Windows, systems that support Modern Standby specify hardware
pre-conditions for the SoC to be able to achieve the lowest power state
by using 'device constraints' in a SOC specific "Power Engine
Plugin" (PEP) [1] [2].

For each device, the constraint is the minimum (shallowest) power
state in which the device can be for the platform to be still able to
achieve significant energy conservation in a system-wide low-power
idle configuration.

Device constraints are specified in the return value for a _DSM of
a PNP0D80 device, and Linux enumerates the constraints during probing.

For PCI bridges (including PCIe ports), the constraints may be
regarded as an additional source of information regarding the power
state to put the device into when it is suspended. In particular, if
the constraint for a given PCI bridge is D3hot, the platform regards
D3hot as a valid power state for the bridge and it is reasonable to
expect that there won't be any side effects caused by putting the
bridge into that power state.

Accordingly, take the low-power S0 idle (LPS0) constraints into
account when deciding whether or not to allow a given PCI bridge to be
put into D3.

Link: https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/platform-design-for-modern-standby#low-power-core-silicon-cpu-soc-dram [1]
Link: https://uefi.org/sites/default/files/resources/Intel_ACPI_Low_Power_S0_Idle.pdf [2]
Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
---
v13->v14:
* Move code as another way to satisfy acpi_pci_bridge_d3() instead
* Update commit with Rafael's suggestions
v12->v13:
* Move back to PCI code
* Trim commit message
v11->v12:
* Adjust for dropped patch 8/9 from v11.
* Update comment
v10->v11:
* Fix kernel kernel build robot errors and various sparse warnings
related to new handling of pci_power_t.
* Use the new helpers introduced in previous patches
---
drivers/pci/pci-acpi.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 64e6ada024235..8331aea22d327 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1022,6 +1022,15 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)

adev = ACPI_COMPANION(&dev->dev);
if (adev) {
+ int acpi_state;
+
+ /* Check if the platform specifies an LPS0 constraint of D3. */
+ acpi_state = acpi_get_lps0_constraint(adev);
+ pci_dbg(dev, "LPS0 constraint: %d\n", acpi_state);
+ if (acpi_state != ACPI_STATE_UNKNOWN &&
+ acpi_state >= ACPI_STATE_D3_HOT)
+ return true;
+
/*
* If the bridge has _S0W, whether or not it can go into D3
* depends on what is returned by that object. In particular,
--
2.34.1