For endpoints, change pcie_aspm_exit_link_state() so it cleans up
the device's own state and disables ASPM if necessary, but doesn't
remove the parent's link_state.

For bridges, change pcie_aspm_exit_link_state() so it frees the
bridge's own link_state.

Signed-off-by: Sinan Kaya <[email protected]>
---
 drivers/pci/pcie/aspm.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index ed67710..6c2d7ea 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -419,8 +419,10 @@ static void pcie_aspm_cap_init(struct pcie_link_state 
*link,
         */
        if (dwreg.support & upreg.support & PCIE_LINK_STATE_L0S)
                link->aspm_support |= ASPM_STATE_L0S;
-       if (dwreg.enabled & PCIE_LINK_STATE_L0S)
+       if (dwreg.enabled & PCIE_LINK_STATE_L0S) {
                link->aspm_enabled |= ASPM_STATE_L0S_UP;
+               link->aspm_default |= ASPM_STATE_L0S_UP;
+       }
        if (upreg.enabled & PCIE_LINK_STATE_L0S)
                link->aspm_enabled |= ASPM_STATE_L0S_DW;
        link->latency_up.l0s = calc_l0s_latency(upreg.latency_encoding_l0s);
@@ -434,9 +436,6 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link,
        link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1);
        link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1);
 
-       /* Save default state */
-       link->aspm_default = link->aspm_enabled;
-
        /* Setup initial capable state. Will be updated later */
        link->aspm_capable = link->aspm_support;
 }
@@ -579,6 +578,7 @@ int pci_aspm_init(struct pci_dev *pdev)
 {
        int ret;
        struct pcie_link_state *link;
+       struct aspm_register_info upreg;
 
        if (!aspm_support_enabled)
                return 0;
@@ -601,6 +601,13 @@ int pci_aspm_init(struct pci_dev *pdev)
                        ret = -ENOMEM;
                        goto unlock;
                }
+
+               pcie_get_aspm_reg(pdev, &upreg);
+               if (upreg.enabled & PCIE_LINK_STATE_L0S)
+                       link->aspm_default |= ASPM_STATE_L0S_DW;
+               if (upreg.enabled & PCIE_LINK_STATE_L1)
+                       link->aspm_default |= ASPM_STATE_L1;
+
        } else {
                WARN_ON(!pdev->bus);
                if (!pdev->bus) {
@@ -748,10 +755,12 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
 
        /* All functions are removed, so just disable ASPM for the link */
        pcie_config_aspm_link(link, 0);
-       list_del(&link->sibling);
-       list_del(&link->link);
-       /* Clock PM is for endpoint device */
-       free_link_state(link);
+       if (pdev->has_secondary_link) {
+               list_del(&link->sibling);
+               list_del(&link->link);
+               /* Clock PM is for endpoint device */
+               free_link_state(link);
+       }
 
        /* Recheck latencies and configure upstream links */
        if (parent_link) {
-- 
1.9.1

Reply via email to