Subject: [PATCH] PCI, ACPI: Delay pcie_no_aspm() calling

Roman reported ath5k does not work anymore on 3.8.
Bisected to
| commit 8c33f51df406e1a1f7fa4e9b244845b7ebd61fa6
| Author: Taku Izumi <izumi.taku@jp.fujitsu.com>
| Date:   Tue Oct 30 15:27:13 2012 +0900
|
|    PCI/ACPI: Request _OSC control before scanning PCI root bus
|
|    This patch moves up the code block to request _OSC control in order to
|    separate ACPI work and PCI work in acpi_pci_root_add().

It make pci_disable_link_state does not work anymore as acpi_disabled
is set before pci root bus scanning.
It will skip that in quirks and pcie_aspm_sanity_check.

Retore old logic just delay calling pcie_no_aspm() later.

https://bugzilla.kernel.org/show_bug.cgi?id=55211
http://article.gmane.org/gmane.linux.kernel.pci/20640

Need it for 3.8 stable.

Reported-by: Roman Yepishev <roman.yepishev@gmail.com>
Bisected-by: Roman Yepishev <roman.yepishev@gmail.com>
Tested-by: Roman Yepishev <roman.yepishev@gmail.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: stable@kernel.org

---
 drivers/acpi/pci_root.c |   28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_root.c
+++ linux-2.6/drivers/acpi/pci_root.c
@@ -415,7 +415,9 @@ static int acpi_pci_root_add(struct acpi
 	struct acpi_pci_root *root;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
-	bool is_osc_granted = false;
+	/* -1: not even tried, 0: tried but failed, 1: tried and succesful */
+	int osc_support_query_state = -1;
+	int osc_control_set_state = -1;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
@@ -488,11 +490,12 @@ static int acpi_pci_root_add(struct acpi
 	if (flags != base_flags) {
 		status = acpi_pci_osc_support(root, flags);
 		if (ACPI_FAILURE(status)) {
+			osc_support_query_state = 0;
 			dev_info(&device->dev, "ACPI _OSC support "
-				"notification failed, disabling PCIe ASPM\n");
-			pcie_no_aspm();
+				"notification failed, PCIe ASPM will be disabled\n");
 			flags = base_flags;
-		}
+		} else
+			osc_support_query_state = 1;
 	}
 	if (!pcie_ports_disabled
 	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
@@ -514,11 +517,11 @@ static int acpi_pci_root_add(struct acpi
 		status = acpi_pci_osc_control_set(device->handle, &flags,
 				       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 		if (ACPI_SUCCESS(status)) {
-			is_osc_granted = true;
+			osc_control_set_state = 1;
 			dev_info(&device->dev,
 				"ACPI _OSC control (0x%02x) granted\n", flags);
 		} else {
-			is_osc_granted = false;
+			osc_control_set_state = 0;
 			dev_info(&device->dev,
 				"ACPI _OSC request failed (%s), "
 				"returned control mask: 0x%02x\n",
@@ -555,13 +558,16 @@ static int acpi_pci_root_add(struct acpi
 	}
 
 	/* ASPM setting */
-	if (is_osc_granted) {
+	if (osc_support_query_state == 0) {
+		dev_info(&device->dev, "ACPI _OSC support notification failed, PCIe ASPM disabled\n");
+		pcie_no_aspm();
+	}
+	if (osc_control_set_state == 1) {
 		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
 			pcie_clear_aspm(root->bus);
-	} else {
-		pr_info("ACPI _OSC control for PCIe not granted, "
-			"disabling ASPM\n");
-		pcie_no_aspm();
+	} else if (osc_control_set_state == 0) {
+			dev_info(&device->dev, "ACPI _OSC control not granted, PCIe ASPM disabled\n");
+			pcie_no_aspm();
 	}
 
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
