aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2009-02-17 00:13:59 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-20 13:48:02 -0400
commitd391f00f0e7fb6d883c6724b31a1799e19a584c5 (patch)
tree02d81d24488963f97c6d4d2e102ead27fcf78ae5 /drivers/pci
parent267efd7eec5eca62f32f8c9bc1721b578d5da963 (diff)
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: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c34
1 files changed, 12 insertions, 22 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 09a84402986d..fbc63d5e459f 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -372,12 +372,10 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
372 * 372 *
373 * Attempt to take hotplug control from firmware. 373 * Attempt to take hotplug control from firmware.
374 */ 374 */
375int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) 375int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
376{ 376{
377 acpi_status status; 377 acpi_status status;
378 acpi_handle chandle, handle; 378 acpi_handle chandle, handle;
379 struct pci_dev *pdev = dev;
380 struct pci_bus *parent;
381 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; 379 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
382 380
383 flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | 381 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 string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; 407 string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
410 } 408 }
411 409
412 pdev = dev; 410 handle = DEVICE_ACPI_HANDLE(&pdev->dev);
413 handle = DEVICE_ACPI_HANDLE(&dev->dev); 411 if (!handle) {
414 while (!handle) {
415 /* 412 /*
416 * This hotplug controller was not listed in the ACPI name 413 * This hotplug controller was not listed in the ACPI name
417 * space at all. Try to get acpi handle of parent pci bus. 414 * space at all. Try to get acpi handle of parent pci bus.
418 */ 415 */
419 if (!pdev || !pdev->bus->parent) 416 struct pci_bus *pbus;
420 break; 417 for (pbus = pdev->bus; pbus; pbus = pbus->parent) {
421 parent = pdev->bus->parent; 418 handle = acpi_pci_get_bridge_handle(pbus);
422 dbg("Could not find %s in acpi namespace, trying parent\n", 419 if (handle)
423 pci_name(pdev)); 420 break;
424 if (!parent->self) 421 }
425 /* Parent must be a host bridge */
426 handle = acpi_get_pci_rootbridge_handle(
427 pci_domain_nr(parent),
428 parent->number);
429 else
430 handle = DEVICE_ACPI_HANDLE(&(parent->self->dev));
431 pdev = parent->self;
432 } 422 }
433 423
434 while (handle) { 424 while (handle) {
@@ -447,13 +437,13 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
447 } 437 }
448 438
449 dbg("Cannot get control of hotplug hardware for pci %s\n", 439 dbg("Cannot get control of hotplug hardware for pci %s\n",
450 pci_name(dev)); 440 pci_name(pdev));
451 441
452 kfree(string.pointer); 442 kfree(string.pointer);
453 return -ENODEV; 443 return -ENODEV;
454got_one: 444got_one:
455 dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), 445 dbg("Gained control for hotplug HW for pci %s (%s)\n",
456 (char *)string.pointer); 446 pci_name(pdev), (char *)string.pointer);
457 kfree(string.pointer); 447 kfree(string.pointer);
458 return 0; 448 return 0;
459} 449}