Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / pci / pcie / aspm.c
index 7d4fcdc..c6a012b 100644 (file)
@@ -127,15 +127,12 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
 {
        struct pci_dev *child;
        struct pci_bus *linkbus = link->pdev->subordinate;
+       u32 val = enable ? PCI_EXP_LNKCTL_CLKREQ_EN : 0;
 
-       list_for_each_entry(child, &linkbus->devices, bus_list) {
-               if (enable)
-                       pcie_capability_set_word(child, PCI_EXP_LNKCTL,
-                                                PCI_EXP_LNKCTL_CLKREQ_EN);
-               else
-                       pcie_capability_clear_word(child, PCI_EXP_LNKCTL,
-                                                  PCI_EXP_LNKCTL_CLKREQ_EN);
-       }
+       list_for_each_entry(child, &linkbus->devices, bus_list)
+               pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
+                                                  PCI_EXP_LNKCTL_CLKREQ_EN,
+                                                  val);
        link->clkpm_enabled = !!enable;
 }
 
@@ -521,25 +518,32 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
        link = kzalloc(sizeof(*link), GFP_KERNEL);
        if (!link)
                return NULL;
+
        INIT_LIST_HEAD(&link->sibling);
        INIT_LIST_HEAD(&link->children);
        INIT_LIST_HEAD(&link->link);
        link->pdev = pdev;
-       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) {
+
+       /*
+        * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
+        * hierarchies.
+        */
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
+           pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) {
+               link->root = link;
+       } else {
                struct pcie_link_state *parent;
+
                parent = pdev->bus->parent->self->link_state;
                if (!parent) {
                        kfree(link);
                        return NULL;
                }
+
                link->parent = parent;
+               link->root = link->parent->root;
                list_add(&link->link, &parent->children);
        }
-       /* Setup a pointer to the root port link */
-       if (!link->parent)
-               link->root = link;
-       else
-               link->root = link->parent->root;
 
        list_add(&link->sibling, &link_list);
        pdev->link_state = link;
@@ -559,10 +563,15 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
        if (!aspm_support_enabled)
                return;
 
-       if (!pci_is_pcie(pdev) || pdev->link_state)
+       if (pdev->link_state)
                return;
-       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-           pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
+
+       /*
+        * We allocate pcie_link_state for the component on the upstream
+        * end of a Link, so there's nothing to do unless this device has a
+        * Link on its secondary side.
+        */
+       if (!pdev->has_secondary_link)
                return;
 
        /* VIA has a strange chipset, root port is under a bridge */
@@ -675,10 +684,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
 {
        struct pcie_link_state *link = pdev->link_state;
 
-       if (aspm_disabled || !pci_is_pcie(pdev) || !link)
-               return;
-       if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
-           (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
+       if (aspm_disabled || !link)
                return;
        /*
         * Devices changed PM state, we should recheck if latency
@@ -696,16 +702,12 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
 {
        struct pcie_link_state *link = pdev->link_state;
 
-       if (aspm_disabled || !pci_is_pcie(pdev) || !link)
+       if (aspm_disabled || !link)
                return;
 
        if (aspm_policy != POLICY_POWERSAVE)
                return;
 
-       if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
-           (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
-               return;
-
        down_read(&pci_bus_sem);
        mutex_lock(&aspm_lock);
        pcie_config_aspm_path(link);
@@ -714,8 +716,7 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
        up_read(&pci_bus_sem);
 }
 
-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
-                                    bool force)
+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 {
        struct pci_dev *parent = pdev->bus->self;
        struct pcie_link_state *link;
@@ -723,8 +724,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
        if (!pci_is_pcie(pdev))
                return;
 
-       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
-           pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)
+       if (pdev->has_secondary_link)
                parent = pdev;
        if (!parent || !parent->link_state)
                return;
@@ -737,7 +737,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
         * a similar mechanism using "PciASPMOptOut", which is also
         * ignored in this situation.
         */
-       if (aspm_disabled && !force) {
+       if (aspm_disabled) {
                dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n");
                return;
        }
@@ -763,7 +763,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
 
 void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
 {
-       __pci_disable_link_state(pdev, state, false, false);
+       __pci_disable_link_state(pdev, state, false);
 }
 EXPORT_SYMBOL(pci_disable_link_state_locked);
 
@@ -778,7 +778,7 @@ EXPORT_SYMBOL(pci_disable_link_state_locked);
  */
 void pci_disable_link_state(struct pci_dev *pdev, int state)
 {
-       __pci_disable_link_state(pdev, state, true, false);
+       __pci_disable_link_state(pdev, state, true);
 }
 EXPORT_SYMBOL(pci_disable_link_state);
 
@@ -907,9 +907,7 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
 {
        struct pcie_link_state *link_state = pdev->link_state;
 
-       if (!pci_is_pcie(pdev) ||
-           (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-            pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+       if (!link_state)
                return;
 
        if (link_state->aspm_support)
@@ -924,9 +922,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
 {
        struct pcie_link_state *link_state = pdev->link_state;
 
-       if (!pci_is_pcie(pdev) ||
-           (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-            pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+       if (!link_state)
                return;
 
        if (link_state->aspm_support)