aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c41
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);
382int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) 382int 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;
464got_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}
453EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); 470EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
454 471