diff options
| -rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 93e37f0666ab..bd831970f00b 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | |||
| 382 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | 382 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) |
| 383 | { | 383 | { |
| 384 | acpi_status status; | 384 | acpi_status status; |
| 385 | acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); | 385 | acpi_handle chandle, handle; |
| 386 | struct pci_dev *pdev = dev; | 386 | struct pci_dev *pdev = dev; |
| 387 | struct pci_bus *parent; | 387 | struct pci_bus *parent; |
| 388 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 388 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -399,10 +399,28 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 399 | * Per PCI firmware specification, we should run the ACPI _OSC | 399 | * Per PCI firmware specification, we should run the ACPI _OSC |
| 400 | * method to get control of hotplug hardware before using it. If | 400 | * method to get control of hotplug hardware before using it. If |
| 401 | * an _OSC is missing, we look for an OSHP to do the same thing. | 401 | * an _OSC is missing, we look for an OSHP to do the same thing. |
| 402 | * To handle different BIOS behavior, we look for _OSC and OSHP | 402 | * To handle different BIOS behavior, we look for _OSC on a root |
| 403 | * within the scope of the hotplug controller and its parents, | 403 | * bridge preferentially (according to PCI fw spec). Later for |
| 404 | * OSHP within the scope of the hotplug controller and its parents, | ||
| 404 | * upto the host bridge under which this controller exists. | 405 | * upto the host bridge under which this controller exists. |
| 405 | */ | 406 | */ |
| 407 | while (pdev->bus->self) | ||
| 408 | pdev = pdev->bus->self; | ||
| 409 | handle = acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus), | ||
| 410 | pdev->bus->number); | ||
| 411 | if (handle) { | ||
| 412 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
| 413 | dbg("Trying to get hotplug control for %s\n", | ||
| 414 | (char *)string.pointer); | ||
| 415 | status = pci_osc_control_set(handle, flags); | ||
| 416 | if (ACPI_SUCCESS(status)) | ||
| 417 | goto got_one; | ||
| 418 | kfree(string.pointer); | ||
| 419 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 420 | } | ||
| 421 | |||
| 422 | pdev = dev; | ||
| 423 | handle = DEVICE_ACPI_HANDLE(&dev->dev); | ||
| 406 | while (!handle) { | 424 | while (!handle) { |
| 407 | /* | 425 | /* |
| 408 | * This hotplug controller was not listed in the ACPI name | 426 | * This hotplug controller was not listed in the ACPI name |
| @@ -427,15 +445,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 427 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 445 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
| 428 | dbg("Trying to get hotplug control for %s \n", | 446 | dbg("Trying to get hotplug control for %s \n", |
| 429 | (char *)string.pointer); | 447 | (char *)string.pointer); |
| 430 | status = pci_osc_control_set(handle, flags); | 448 | status = acpi_run_oshp(handle); |
| 431 | if (status == AE_NOT_FOUND) | 449 | if (ACPI_SUCCESS(status)) |
| 432 | status = acpi_run_oshp(handle); | 450 | goto got_one; |
| 433 | if (ACPI_SUCCESS(status)) { | ||
| 434 | dbg("Gained control for hotplug HW for pci %s (%s)\n", | ||
| 435 | pci_name(dev), (char *)string.pointer); | ||
| 436 | kfree(string.pointer); | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | if (acpi_root_bridge(handle)) | 451 | if (acpi_root_bridge(handle)) |
| 440 | break; | 452 | break; |
| 441 | chandle = handle; | 453 | chandle = handle; |
| @@ -449,6 +461,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
| 449 | 461 | ||
| 450 | kfree(string.pointer); | 462 | kfree(string.pointer); |
| 451 | return -ENODEV; | 463 | return -ENODEV; |
| 464 | got_one: | ||
| 465 | dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), | ||
| 466 | (char *)string.pointer); | ||
| 467 | kfree(string.pointer); | ||
| 468 | return 0; | ||
| 452 | } | 469 | } |
| 453 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); | 470 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); |
| 454 | 471 | ||
