Commit d391f00f authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Jesse Barnes

PCI hotplug: fix wrong assumption in acpi_get_hp_hw_control_from_firmware

Current acpi_get_hp_hw_control_from_firmware() has a assumption that
pci_bus->self is NULL on a PCI root bus. But it might not be true on
some platforms. Because of this wrong assumption, current
acpi_get_hp_hw_control_from_firmware() might cause endless loop. We
must check pci_bus->parent instead.
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 267efd7e
...@@ -372,12 +372,10 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); ...@@ -372,12 +372,10 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
* *
* Attempt to take hotplug control from firmware. * Attempt to take hotplug control from firmware.
*/ */
int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
{ {
acpi_status status; acpi_status status;
acpi_handle chandle, handle; acpi_handle chandle, handle;
struct pci_dev *pdev = dev;
struct pci_bus *parent;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
...@@ -409,26 +407,18 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) ...@@ -409,26 +407,18 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
} }
pdev = dev; handle = DEVICE_ACPI_HANDLE(&pdev->dev);
handle = DEVICE_ACPI_HANDLE(&dev->dev); if (!handle) {
while (!handle) {
/* /*
* This hotplug controller was not listed in the ACPI name * This hotplug controller was not listed in the ACPI name
* space at all. Try to get acpi handle of parent pci bus. * space at all. Try to get acpi handle of parent pci bus.
*/ */
if (!pdev || !pdev->bus->parent) struct pci_bus *pbus;
for (pbus = pdev->bus; pbus; pbus = pbus->parent) {
handle = acpi_pci_get_bridge_handle(pbus);
if (handle)
break; break;
parent = pdev->bus->parent; }
dbg("Could not find %s in acpi namespace, trying parent\n",
pci_name(pdev));
if (!parent->self)
/* Parent must be a host bridge */
handle = acpi_get_pci_rootbridge_handle(
pci_domain_nr(parent),
parent->number);
else
handle = DEVICE_ACPI_HANDLE(&(parent->self->dev));
pdev = parent->self;
} }
while (handle) { while (handle) {
...@@ -447,13 +437,13 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) ...@@ -447,13 +437,13 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
} }
dbg("Cannot get control of hotplug hardware for pci %s\n", dbg("Cannot get control of hotplug hardware for pci %s\n",
pci_name(dev)); pci_name(pdev));
kfree(string.pointer); kfree(string.pointer);
return -ENODEV; return -ENODEV;
got_one: got_one:
dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), dbg("Gained control for hotplug HW for pci %s (%s)\n",
(char *)string.pointer); pci_name(pdev), (char *)string.pointer);
kfree(string.pointer); kfree(string.pointer);
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