Commit 7430e34c authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Greg Kroah-Hartman

[PATCH] acpi_pcihp: Fix programming _HPP values

This patch fixes the problem that hotplug parameters are not programed
when PCI cards are hot-added by ACPIPHP, SHPCHP and PCIEHP driver. The
pci_dev structure being hot-added is not bound to ACPI handle, so we
need to trace PCI bus tree to find ACPI handle.
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 2433ee26
...@@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); ...@@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp);
/* acpi_get_hp_params_from_firmware /* 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 * @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) struct hotplug_params *hpp)
{ {
acpi_status status = AE_NOT_FOUND; 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 * _HPP settings apply to all child buses, until another _HPP is
...@@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, ...@@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
* look for it in the parent device scope since that would apply to * 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 * this pci dev. If we don't find any _HPP, use hardcoded defaults
*/ */
while (pdev && (ACPI_FAILURE(status))) { while (handle) {
acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
if (!handle)
break;
status = acpi_run_hpp(handle, hpp); 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; break;
/* Check if a parent object supports _HPP */ handle = phandle;
pdev = pdev->bus->parent->self;
} }
return status; return status;
} }
......
...@@ -286,7 +286,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge) ...@@ -286,7 +286,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
{ {
acpi_status status; 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)) { if (ACPI_FAILURE(status)) {
/* use default numbers */ /* use default numbers */
bridge->hpp.cache_line_size = 0x10; bridge->hpp.cache_line_size = 0x10;
...@@ -1250,6 +1250,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) ...@@ -1250,6 +1250,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
memset(&bridge, 0, sizeof(bridge)); memset(&bridge, 0, sizeof(bridge));
bridge.handle = handle; bridge.handle = handle;
bridge.pci_bus = bus;
bridge.pci_dev = bus->self; bridge.pci_dev = bus->self;
decode_hpp(&bridge); decode_hpp(&bridge);
list_for_each_entry(dev, &bus->devices, bus_list) list_for_each_entry(dev, &bus->devices, bus_list)
......
...@@ -188,7 +188,7 @@ struct hotplug_params { ...@@ -188,7 +188,7 @@ struct hotplug_params {
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/actypes.h> #include <acpi/actypes.h>
extern acpi_status acpi_run_oshp(acpi_handle handle); 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); struct hotplug_params *hpp);
int acpi_root_bridge(acpi_handle handle); int acpi_root_bridge(acpi_handle handle);
#endif #endif
......
...@@ -284,7 +284,7 @@ struct hpc_ops { ...@@ -284,7 +284,7 @@ struct hpc_ops {
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp) 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 -ENODEV;
return 0; return 0;
} }
......
...@@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void *data); ...@@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void *data);
static inline int get_hp_params_from_firmware(struct pci_dev *dev, static inline int get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp) 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 -ENODEV;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment