diff options
Diffstat (limited to 'drivers/pci/hotplug/acpi_pcihp.c')
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 5bd6c1573295..6b7c1ed58e7e 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -74,20 +74,6 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev) struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; /* - * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it. If - * an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC on a root - * bridge preferentially (according to PCI fw spec). Later for - * OSHP within the scope of the hotplug controller and its parents, - * up to the host bridge under which this controller exists. - */ - if (shpchp_is_native(pdev)) - return 0; - - /* If _OSC exists, we should not evaluate OSHP */ - - /* * If there's no ACPI host bridge (i.e., ACPI support is compiled * into the kernel but the hardware platform doesn't support ACPI), * there's nothing to do here. @@ -97,9 +83,25 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev) if (!root) return 0; - if (root->osc_support_set) - goto no_control; + /* + * If _OSC exists, it determines whether we're allowed to manage + * the SHPC. We executed it while enumerating the host bridge. + */ + if (root->osc_support_set) { + if (host->native_shpc_hotplug) + return 0; + return -ENODEV; + } + /* + * In the absence of _OSC, we're always allowed to manage the SHPC. + * However, if an OSHP method is present, we must execute it so the + * firmware can transfer control to the OS, e.g., direct interrupts + * to the OS instead of to the firmware. + * + * N.B. The PCI Firmware Spec (r3.2, sec 4.8) does not endorse + * searching up the ACPI hierarchy, so the loops below are suspect. + */ handle = ACPI_HANDLE(&pdev->dev); if (!handle) { /* @@ -128,7 +130,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev) if (ACPI_FAILURE(status)) break; } -no_control: + pci_info(pdev, "Cannot get control of SHPC hotplug\n"); kfree(string.pointer); return -ENODEV; |