Merge tag 'v3.10.104' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / acpi / pci_root.c
index a02a91cd1de4d48fcd62c8cf4c71fa7f41249415..c5e3dd93865a85c0251da692d683b59ad4ede2ba 100644 (file)
@@ -385,6 +385,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
        int result;
        struct acpi_pci_root *root;
        u32 flags, base_flags;
+       bool no_aspm = false, clear_aspm = false;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
@@ -445,31 +446,10 @@ static int acpi_pci_root_add(struct acpi_device *device,
        flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
        acpi_pci_osc_support(root, flags);
 
-       /*
-        * TBD: Need PCI interface for enumeration/configuration of roots.
-        */
-
        mutex_lock(&acpi_pci_root_lock);
        list_add_tail(&root->node, &acpi_pci_roots);
        mutex_unlock(&acpi_pci_root_lock);
 
-       /*
-        * Scan the Root Bridge
-        * --------------------
-        * Must do this prior to any attempt to bind the root device, as the
-        * PCI namespace does not get created until this call is made (and
-        * thus the root bridge's pci_dev does not exist).
-        */
-       root->bus = pci_acpi_scan_root(root);
-       if (!root->bus) {
-               printk(KERN_ERR PREFIX
-                           "Bus %04x:%02x not present in PCI namespace\n",
-                           root->segment, (unsigned int)root->secondary.start);
-               result = -ENODEV;
-               goto out_del_root;
-       }
-
-       /* Indicate support for various _OSC capabilities. */
        if (pci_ext_cfg_avail())
                flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
        if (pcie_aspm_support_enabled()) {
@@ -483,7 +463,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
                if (ACPI_FAILURE(status)) {
                        dev_info(&device->dev, "ACPI _OSC support "
                                "notification failed, disabling PCIe ASPM\n");
-                       pcie_no_aspm();
+                       no_aspm = true;
                        flags = base_flags;
                }
        }
@@ -515,7 +495,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
                                 * We have ASPM control, but the FADT indicates
                                 * that it's unsupported. Clear it.
                                 */
-                               pcie_clear_aspm(root->bus);
+                               clear_aspm = true;
                        }
                } else {
                        dev_info(&device->dev,
@@ -524,7 +504,14 @@ static int acpi_pci_root_add(struct acpi_device *device,
                                acpi_format_exception(status), flags);
                        pr_info("ACPI _OSC control for PCIe not granted, "
                                "disabling ASPM\n");
-                       pcie_no_aspm();
+                       /*
+                        * We want to disable ASPM here, but aspm_disabled
+                        * needs to remain in its state from boot so that we
+                        * properly handle PCIe 1.1 devices.  So we set this
+                        * flag here, to defer the action until after the ACPI
+                        * root scan.
+                        */
+                       no_aspm = true;
                }
        } else {
                dev_info(&device->dev,
@@ -532,6 +519,33 @@ static int acpi_pci_root_add(struct acpi_device *device,
                         "(_OSC support mask: 0x%02x)\n", flags);
        }
 
+       /*
+        * TBD: Need PCI interface for enumeration/configuration of roots.
+        */
+
+       /*
+        * Scan the Root Bridge
+        * --------------------
+        * Must do this prior to any attempt to bind the root device, as the
+        * PCI namespace does not get created until this call is made (and
+        * thus the root bridge's pci_dev does not exist).
+        */
+       root->bus = pci_acpi_scan_root(root);
+       if (!root->bus) {
+               dev_err(&device->dev,
+                       "Bus %04x:%02x not present in PCI namespace\n",
+                       root->segment, (unsigned int)root->secondary.start);
+               result = -ENODEV;
+               goto end;
+       }
+
+       if (clear_aspm) {
+               dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n");
+               pcie_clear_aspm(root->bus);
+       }
+       if (no_aspm)
+               pcie_no_aspm();
+
        pci_acpi_add_bus_pm_notifier(device, root->bus);
        if (device->wakeup.flags.run_wake)
                device_set_run_wake(root->bus->bridge, true);
@@ -548,11 +562,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
        pci_bus_add_devices(root->bus);
        return 1;
 
-out_del_root:
-       mutex_lock(&acpi_pci_root_lock);
-       list_del(&root->node);
-       mutex_unlock(&acpi_pci_root_lock);
-
 end:
        kfree(root);
        return result;