--- drivers/acpi/bus.c | 6 ++++++ drivers/acpi/device_pm.c | 30 ++++++++++++++++++++++++++++++ drivers/acpi/pci_root.c | 2 ++ drivers/pci/pci-acpi.c | 3 +++ include/acpi/acpi_bus.h | 3 +++ 5 files changed, 44 insertions(+) Index: linux-pm/drivers/acpi/bus.c =================================================================== --- linux-pm.orig/drivers/acpi/bus.c +++ linux-pm/drivers/acpi/bus.c @@ -1070,6 +1070,12 @@ int acpi_bus_for_each_dev(int (*fn)(stru } EXPORT_SYMBOL_GPL(acpi_bus_for_each_dev); +int acpi_dev_for_each_child(struct acpi_device *adev, + int (*fn)(struct device *, void *), void *data) +{ + return device_for_each_child(&adev->dev, data, fn); +} + /* -------------------------------------------------------------------------- Initialization/Cleanup -------------------------------------------------------------------------- */ Index: linux-pm/include/acpi/acpi_bus.h =================================================================== --- linux-pm.orig/include/acpi/acpi_bus.h +++ linux-pm/include/acpi/acpi_bus.h @@ -481,6 +481,8 @@ void acpi_initialize_hp_context(struct a extern struct bus_type acpi_bus_type; int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data); +int acpi_dev_for_each_child(struct acpi_device *adev, + int (*fn)(struct device *, void *), void *data); /* * Events @@ -523,6 +525,7 @@ int acpi_device_fix_up_power(struct acpi int acpi_bus_update_power(acpi_handle handle, int *state_p); int acpi_device_update_power(struct acpi_device *device, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); +void acpi_dev_power_up_children_with_adr(struct acpi_device *adev); int acpi_device_power_add_dependent(struct acpi_device *adev, struct device *dev); void acpi_device_power_remove_dependent(struct acpi_device *adev, Index: linux-pm/drivers/acpi/device_pm.c =================================================================== --- linux-pm.orig/drivers/acpi/device_pm.c +++ linux-pm/drivers/acpi/device_pm.c @@ -425,6 +425,36 @@ bool acpi_bus_power_manageable(acpi_hand } EXPORT_SYMBOL(acpi_bus_power_manageable); +static int acpi_power_up_if_adr_present(struct device *dev, void *not_used) +{ + struct acpi_device *adev; + + adev = to_acpi_device(dev); + if (!adev->pnp.type.bus_address) + return 0; + + acpi_handle_info(adev->handle, "Power state: %s\n", + acpi_power_state_string(adev->power.state)); + + if (adev->power.state == ACPI_STATE_D3_COLD) + return acpi_device_set_power(adev, ACPI_STATE_D0); + + return 0; +} + +/** + * acpi_dev_power_up_children_with_adr - Power up childres with valid _ADR + * @adev: Parent ACPI device object. + * + * Change the power states of the direct children of @adev that are in D3cold + * and hold valid _ADR objects to D0 in order to allow bus (e.g. PCI) + * enumeration code to access them. + */ +void acpi_dev_power_up_children_with_adr(struct acpi_device *adev) +{ + acpi_dev_for_each_child(adev, acpi_power_up_if_adr_present, NULL); +} + #ifdef CONFIG_PM static DEFINE_MUTEX(acpi_pm_notifier_lock); static DEFINE_MUTEX(acpi_pm_notifier_install_lock); 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)