PCI/ASPM: Remove struct aspm_register_info.support
authorSaheed O. Bolarinwa <refactormyself@gmail.com>
Thu, 15 Oct 2020 19:30:31 +0000 (14:30 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 16 Oct 2020 16:20:53 +0000 (11:20 -0500)
Previously we stored the "ASPM Support" field from the Link Capabilities
register in the struct aspm_register_info.

Read the Link Capabilities directly when needed and remove it from the
struct aspm_register_info.  No functional change intended.

[bhelgaas: remove pci_dev cached copy since LNKCAP isn't truly read-only,
add PCI_EXP_LNKCAP_ASPM_L0S & PCI_EXP_LNKCAP_ASPM_L1, check them directly
instead of adding aspm_support()]
Link: https://lore.kernel.org/r/20201015193039.12585-5-helgaas@kernel.org
Signed-off-by: Saheed O. Bolarinwa <refactormyself@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pcie/aspm.c
include/uapi/linux/pci_regs.h

index 0725511..82ce34e 100644 (file)
@@ -381,7 +381,6 @@ static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
 }
 
 struct aspm_register_info {
-       u32 support:2;
        u32 enabled:2;
        u32 latency_encoding_l0s;
        u32 latency_encoding_l1;
@@ -400,7 +399,6 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev,
        u32 reg32;
 
        pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &reg32);
-       info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
        info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
        info->latency_encoding_l1  = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
        pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &reg16);
@@ -550,6 +548,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
 static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 {
        struct pci_dev *child = link->downstream, *parent = link->pdev;
+       u32 parent_lnkcap, child_lnkcap;
        struct pci_bus *linkbus = parent->subordinate;
        struct aspm_register_info upreg, dwreg;
 
@@ -560,24 +559,26 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
                return;
        }
 
-       /* Get upstream/downstream components' register state */
-       pcie_get_aspm_reg(parent, &upreg);
-       pcie_get_aspm_reg(child, &dwreg);
-
        /*
         * If ASPM not supported, don't mess with the clocks and link,
         * bail out now.
         */
-       if (!(upreg.support & dwreg.support))
+       pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
+       pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
+       if (!(parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPMS))
                return;
 
        /* Configure common clock before checking latencies */
        pcie_aspm_configure_common_clock(link);
 
        /*
-        * Re-read upstream/downstream components' register state
-        * after clock configuration
+        * Re-read upstream/downstream components' register state after
+        * clock configuration.  L0s & L1 exit latencies in the otherwise
+        * read-only Link Capabilities may change depending on common clock
+        * configuration (PCIe r5.0, sec 7.5.3.6).
         */
+       pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
+       pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
        pcie_get_aspm_reg(parent, &upreg);
        pcie_get_aspm_reg(child, &dwreg);
 
@@ -588,8 +589,9 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
         * given link unless components on both sides of the link each
         * support L0s.
         */
-       if (dwreg.support & upreg.support & PCIE_LINK_STATE_L0S)
+       if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L0S)
                link->aspm_support |= ASPM_STATE_L0S;
+
        if (dwreg.enabled & PCIE_LINK_STATE_L0S)
                link->aspm_enabled |= ASPM_STATE_L0S_UP;
        if (upreg.enabled & PCIE_LINK_STATE_L0S)
@@ -598,8 +600,9 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
        link->latency_dw.l0s = calc_l0s_latency(dwreg.latency_encoding_l0s);
 
        /* Setup L1 state */
-       if (upreg.support & dwreg.support & PCIE_LINK_STATE_L1)
+       if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L1)
                link->aspm_support |= ASPM_STATE_L1;
+
        if (upreg.enabled & dwreg.enabled & PCIE_LINK_STATE_L1)
                link->aspm_enabled |= ASPM_STATE_L1;
        link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1);
index f970141..06846ec 100644 (file)
 #define  PCI_EXP_LNKCAP_SLS_32_0GB 0x00000005 /* LNKCAP2 SLS Vector bit 4 */
 #define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
 #define  PCI_EXP_LNKCAP_ASPMS  0x00000c00 /* ASPM Support */
+#define  PCI_EXP_LNKCAP_ASPM_L0S 0x00000400 /* ASPM L0s Support */
+#define  PCI_EXP_LNKCAP_ASPM_L1  0x00000800 /* ASPM L1 Support */
 #define  PCI_EXP_LNKCAP_L0SEL  0x00007000 /* L0s Exit Latency */
 #define  PCI_EXP_LNKCAP_L1EL   0x00038000 /* L1 Exit Latency */
 #define  PCI_EXP_LNKCAP_CLKPM  0x00040000 /* Clock Power Management */