From 415e12b2379239973feab91850b0dce985c6058a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 7 Jan 2011 00:55:09 +0100 Subject: PCI/ACPI: Request _OSC control once for each root bridge (v3) Move the evaluation of acpi_pci_osc_control_set() (to request control of PCI Express native features) into acpi_pci_root_add() to avoid calling it many times for the same root complex with the same arguments. Additionally, check if all of the requisite _OSC support bits are set before calling acpi_pci_osc_control_set() for a given root complex. References: https://bugzilla.kernel.org/show_bug.cgi?id=20232 Reported-by: Ozan Caglayan Tested-by: Ozan Caglayan Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/acpi/pci_root.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers/acpi/pci_root.c') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 96668ad09622..d9766797cd98 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -36,6 +36,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -47,6 +48,11 @@ static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); +#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ + | OSC_ACTIVE_STATE_PWR_SUPPORT \ + | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \ + | OSC_MSI_SUPPORT) + static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, @@ -566,6 +572,33 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); + if (!pcie_ports_disabled + && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL + | OSC_PCI_EXPRESS_PME_CONTROL; + + if (pci_aer_available()) { + if (aer_acpi_firmware_first()) + dev_dbg(root->bus->bridge, + "PCIe errors handled by BIOS.\n"); + else + flags |= OSC_PCI_EXPRESS_AER_CONTROL; + } + + dev_info(root->bus->bridge, + "Requesting ACPI _OSC control (0x%02x)\n", flags); + + status = acpi_pci_osc_control_set(device->handle, &flags, + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + if (ACPI_SUCCESS(status)) + dev_info(root->bus->bridge, + "ACPI _OSC control (0x%02x) granted\n", flags); + else + dev_dbg(root->bus->bridge, + "ACPI _OSC request failed (code %d)\n", status); + } + pci_acpi_add_bus_pm_notifier(device, root->bus); if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); @@ -603,6 +636,8 @@ static int __init acpi_pci_root_init(void) if (acpi_pci_disabled) return 0; + acpi_hest_init(); + pci_acpi_crs_quirks(); if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) return -ENODEV; -- cgit v1.2.3 From d3072e6a7e9bf7aca200370317f8e297be360b17 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 16 Jan 2011 20:44:22 +0100 Subject: ACPI: Fix boot problem related to APEI with acpi_disabled set Commit 415e12b23792 ("PCI/ACPI: Request _OSC control once for each root bridge (v3)") put the acpi_hest_init() call in acpi_pci_root_init() into a wrong place, presumably because the author confused acpi_pci_disabled with acpi_disabled. Bring the code ordering in acpi_pci_root_init() back to sanity. Additionally, make sure that hest_disable is set when acpi_disabled is set, which is going to prevent acpi_hest_parse(), that still may be executed for acpi_disabled=1 through aer_acpi_firmware_first(), from crashing because of uninitialized hest_tab. Reported-and-tested-by: Andres Salomon Signed-off-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds --- drivers/acpi/pci_root.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/pci_root.c') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d9766797cd98..85249395623b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -633,11 +633,11 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) static int __init acpi_pci_root_init(void) { + acpi_hest_init(); + if (acpi_pci_disabled) return 0; - acpi_hest_init(); - pci_acpi_crs_quirks(); if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) return -ENODEV; -- cgit v1.2.3