mirror of https://gitee.com/openkylin/linux.git
[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: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Cc: Kristen Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
2433ee2654
commit
7430e34c70
|
@ -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,
|
||||||
* 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;
|
break;
|
||||||
/* Check if a parent object supports _HPP */
|
if (acpi_root_bridge(handle))
|
||||||
pdev = pdev->bus->parent->self;
|
break;
|
||||||
|
status = acpi_get_parent(handle, &phandle);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
break;
|
||||||
|
handle = phandle;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
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 {
|
||||||
#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 {
|
||||||
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);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue