Jesse Keating 7a32965
From: Matthew Garrett <mjg@redhat.com>
Jesse Keating 7a32965
Subject: ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
Jesse Keating 7a32965
Jesse Keating 7a32965
ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
Jesse Keating 7a32965
Jesse Keating 7a32965
The PCI SIG documentation for the _OSC OS/firmware handshaking interface
Jesse Keating 7a32965
states:
Jesse Keating 7a32965
Jesse Keating 7a32965
"If the _OSC control method is absent from the scope of a host bridge
Jesse Keating 7a32965
device, then the operating system must not enable or attempt to use any
Jesse Keating 7a32965
features defined in this section for the hierarchy originated by the host
Jesse Keating 7a32965
bridge."
Jesse Keating 7a32965
Jesse Keating 7a32965
The obvious interpretation of this is that the OS should not attempt to use
Jesse Keating 7a32965
PCIe hotplug, PME or AER - however, the specification also notes that an
Jesse Keating 7a32965
_OSC method is *required* for PCIe hierarchies, and experimental validation
Jesse Keating 7a32965
with An Alternative OS indicates that it doesn't use any PCIe functionality
Jesse Keating 7a32965
if the _OSC method is missing. That arguably means we shouldn't be using
Jesse Keating 7a32965
MSI or extended config space, but right now our problems seem to be limited
Jesse Keating 7a32965
to vendors being surprised when ASPM gets enabled on machines when other
Jesse Keating 7a32965
OSs refuse to do so. So, for now, let's just disable ASPM if the _OSC
Jesse Keating 7a32965
method doesn't exist or refuses to hand over PCIe capability control.
Jesse Keating 7a32965
Jesse Keating 7a32965
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Jesse Keating 7a32965
---
Jesse Keating 7a32965
Jesse Keating 7a32965
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
Jesse Keating 7a32965
index 4eac593..1f67057 100644
Jesse Keating 7a32965
--- a/drivers/acpi/pci_root.c
Jesse Keating 7a32965
+++ b/drivers/acpi/pci_root.c
Jesse Keating 7a32965
@@ -33,6 +33,7 @@
Jesse Keating 7a32965
 #include <linux/pm_runtime.h>
Jesse Keating 7a32965
 #include <linux/pci.h>
Jesse Keating 7a32965
 #include <linux/pci-acpi.h>
Jesse Keating 7a32965
+#include <linux/pci-aspm.h>
Jesse Keating 7a32965
 #include <linux/acpi.h>
Jesse Keating 7a32965
 #include <linux/slab.h>
Jesse Keating 7a32965
 #include <acpi/acpi_bus.h>
Jesse Keating 7a32965
@@ -543,6 +544,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
Jesse Keating 7a32965
 	if (flags != base_flags)
Jesse Keating 7a32965
 		acpi_pci_osc_support(root, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	status = acpi_pci_osc_control_set(root->device->handle,
Jesse Keating 7a32965
+					  0);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (status == AE_NOT_EXIST) {
Jesse Keating 7a32965
+		printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
Jesse Keating 7a32965
+		pcie_no_aspm();
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
Jesse Keating 7a32965
 	if (device->wakeup.flags.run_wake)
Jesse Keating 7a32965
 		device_set_run_wake(root->bus->bridge, true);