Signed-off-by: Andrew Morton --- drivers/pci/hotplug/acpi_pcihp.c | 34 +++++++++++++++++++-------- drivers/pci/hotplug/acpiphp_glue.c | 3 +- drivers/pci/hotplug/pci_hotplug.h | 2 - drivers/pci/hotplug/pciehp.h | 2 - drivers/pci/hotplug/shpchp.h | 2 - 5 files changed, 29 insertions(+), 14 deletions(-) diff -puN drivers/pci/hotplug/acpi_pcihp.c~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values drivers/pci/hotplug/acpi_pcihp.c --- a/drivers/pci/hotplug/acpi_pcihp.c~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values +++ a/drivers/pci/hotplug/acpi_pcihp.c @@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); /* acpi_get_hp_params_from_firmware * - * @dev - the pci_dev of the newly added device + * @bus - the pci_bus of the bus on which the device is newly added * @hpp - allocated by the caller */ -acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; + acpi_handle handle, phandle; + struct pci_bus *pbus = bus; + struct pci_dev *pdev; + + do { + pdev = pbus->self; + if (!pdev) { + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(pbus), pbus->number); + break; + } + handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); + pbus = pbus->parent; + } while (!handle); /* * _HPP settings apply to all child buses, until another _HPP is @@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firm * look for it in the parent device scope since that would apply to * this pci dev. If we don't find any _HPP, use hardcoded defaults */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) - break; + while (handle) { status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) + if (ACPI_SUCCESS(status)) + break; + if (acpi_root_bridge(handle)) + break; + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; + handle = phandle; } return status; } diff -puN drivers/pci/hotplug/acpiphp_glue.c~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values drivers/pci/hotplug/acpiphp_glue.c --- a/drivers/pci/hotplug/acpiphp_glue.c~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values +++ a/drivers/pci/hotplug/acpiphp_glue.c @@ -345,7 +345,7 @@ static void decode_hpp(struct acpiphp_br { acpi_status status; - status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); + status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); if (ACPI_FAILURE(status)) { /* use default numbers */ bridge->hpp.cache_line_size = 0x10; @@ -1312,6 +1312,7 @@ static void acpiphp_set_hpp_values(acpi_ memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_bus = bus; bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) diff -puN drivers/pci/hotplug/pciehp.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values drivers/pci/hotplug/pciehp.h --- a/drivers/pci/hotplug/pciehp.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values +++ a/drivers/pci/hotplug/pciehp.h @@ -284,7 +284,7 @@ struct hpc_ops { static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } diff -puN drivers/pci/hotplug/pci_hotplug.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values drivers/pci/hotplug/pci_hotplug.h --- a/drivers/pci/hotplug/pci_hotplug.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values +++ a/drivers/pci/hotplug/pci_hotplug.h @@ -188,7 +188,7 @@ struct hotplug_params { #include #include extern acpi_status acpi_run_oshp(acpi_handle handle); -extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp); int acpi_root_bridge(acpi_handle handle); #endif diff -puN drivers/pci/hotplug/shpchp.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values drivers/pci/hotplug/shpchp.h --- a/drivers/pci/hotplug/shpchp.h~gregkh-pci-acpi_pcihp-fix-programming-_hpp-values +++ a/drivers/pci/hotplug/shpchp.h @@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void * static inline int get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } _