diff mbox series

[v1,3/3] PCI: ACPI: PM: Power up devices in D3cold before scanning them

Message ID 5729439.MhkbZ0Pkbq@kreacher
State New
Headers show
Series None | expand

Commit Message

Rafael J. Wysocki April 4, 2022, 3:25 p.m. UTC
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The initial configuration of ACPI power resources on some systems
implies that some PCI devices on them are initially in D3cold.

In some cases, especially for PCIe Root Ports, this is a "logical"
D3cold, meaning that the configuration space of the device is
accessible, but some of its functionality may be missing, but it
very well may be real D3cold, in which case the device will not
be accessible at all.  However, the PCI bus type driver will need
to access its configuration space in order to enumerate it.

To prevent possible device enumeration failures that may ensue as
a result of ACPI power resources being initially in the "off"
state, power up all children of the host bridge ACPI device object
that hold valid _ADR objects (which indicates that they will be
enumerated by the PCI bus type driver) and do that to all children
of the ACPI device objects corresponding to PCI bridges (including
PCIe ports).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/pci_root.c |    2 ++
 drivers/pci/pci-acpi.c  |    3 +++
 2 files changed, 5 insertions(+)

Comments

Bjorn Helgaas April 7, 2022, 5:51 p.m. UTC | #1
On Mon, Apr 04, 2022 at 05:25:04PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The initial configuration of ACPI power resources on some systems
> implies that some PCI devices on them are initially in D3cold.
> 
> In some cases, especially for PCIe Root Ports, this is a "logical"
> D3cold, meaning that the configuration space of the device is
> accessible, but some of its functionality may be missing, but it
> very well may be real D3cold, in which case the device will not
> be accessible at all.  However, the PCI bus type driver will need
> to access its configuration space in order to enumerate it.
> 
> To prevent possible device enumeration failures that may ensue as
> a result of ACPI power resources being initially in the "off"
> state, power up all children of the host bridge ACPI device object
> that hold valid _ADR objects (which indicates that they will be
> enumerated by the PCI bus type driver) and do that to all children
> of the ACPI device objects corresponding to PCI bridges (including
> PCIe ports).
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

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

> ---
>  drivers/acpi/pci_root.c |    2 ++
>  drivers/pci/pci-acpi.c  |    3 +++
>  2 files changed, 5 insertions(+)
> 
> Index: linux-pm/drivers/acpi/pci_root.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/pci_root.c
> +++ linux-pm/drivers/acpi/pci_root.c
> @@ -927,6 +927,8 @@ struct pci_bus *acpi_pci_root_create(str
>  		host_bridge->preserve_config = 1;
>  	ACPI_FREE(obj);
>  
> +	acpi_dev_power_up_children_with_adr(device);
> +
>  	pci_scan_child_bus(bus);
>  	pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
>  				    info);
> Index: linux-pm/drivers/pci/pci-acpi.c
> ===================================================================
> --- linux-pm.orig/drivers/pci/pci-acpi.c
> +++ linux-pm/drivers/pci/pci-acpi.c
> @@ -1374,6 +1374,9 @@ void pci_acpi_setup(struct device *dev,
>  
>  	acpi_pci_wakeup(pci_dev, false);
>  	acpi_device_power_add_dependent(adev, dev);
> +
> +	if (pci_is_bridge(pci_dev))
> +		acpi_dev_power_up_children_with_adr(adev);
>  }
>  
>  void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev)
> 
> 
>
diff mbox series

Patch

Index: linux-pm/drivers/acpi/pci_root.c
===================================================================
--- linux-pm.orig/drivers/acpi/pci_root.c
+++ linux-pm/drivers/acpi/pci_root.c
@@ -927,6 +927,8 @@  struct pci_bus *acpi_pci_root_create(str
 		host_bridge->preserve_config = 1;
 	ACPI_FREE(obj);
 
+	acpi_dev_power_up_children_with_adr(device);
+
 	pci_scan_child_bus(bus);
 	pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
 				    info);
Index: linux-pm/drivers/pci/pci-acpi.c
===================================================================
--- linux-pm.orig/drivers/pci/pci-acpi.c
+++ linux-pm/drivers/pci/pci-acpi.c
@@ -1374,6 +1374,9 @@  void pci_acpi_setup(struct device *dev,
 
 	acpi_pci_wakeup(pci_dev, false);
 	acpi_device_power_add_dependent(adev, dev);
+
+	if (pci_is_bridge(pci_dev))
+		acpi_dev_power_up_children_with_adr(adev);
 }
 
 void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev)