Skip to content

Commit 4495bff

Browse files
committed
PCI/ASPM: Cache L0s/L1 Supported so advertised link states can be overridden
Defective devices sometimes advertise support for ASPM L0s or L1 states even if they don't work correctly. Cache the L0s Supported and L1 Supported bits early in enumeration so HEADER quirks can override the ASPM states advertised in Link Capabilities before pcie_aspm_cap_init() enables ASPM. Signed-off-by: Bjorn Helgaas <[email protected]> Tested-by: Shawn Lin <[email protected]> Reviewed-by: Lukas Wunner <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 3a86608 commit 4495bff

File tree

3 files changed

+13
-8
lines changed

3 files changed

+13
-8
lines changed

drivers/pci/pcie/aspm.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,6 @@ static void pcie_aspm_override_default_link_state(struct pcie_link_state *link)
830830
static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
831831
{
832832
struct pci_dev *child = link->downstream, *parent = link->pdev;
833-
u32 parent_lnkcap, child_lnkcap;
834833
u16 parent_lnkctl, child_lnkctl;
835834
struct pci_bus *linkbus = parent->subordinate;
836835

@@ -845,9 +844,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
845844
* If ASPM not supported, don't mess with the clocks and link,
846845
* bail out now.
847846
*/
848-
pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
849-
pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
850-
if (!(parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPMS))
847+
if (!(parent->aspm_l0s_support && child->aspm_l0s_support) &&
848+
!(parent->aspm_l1_support && child->aspm_l1_support))
851849
return;
852850

853851
/* Configure common clock before checking latencies */
@@ -859,8 +857,6 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
859857
* read-only Link Capabilities may change depending on common clock
860858
* configuration (PCIe r5.0, sec 7.5.3.6).
861859
*/
862-
pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
863-
pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
864860
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl);
865861
pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl);
866862

@@ -880,7 +876,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
880876
* given link unless components on both sides of the link each
881877
* support L0s.
882878
*/
883-
if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L0S)
879+
if (parent->aspm_l0s_support && child->aspm_l0s_support)
884880
link->aspm_support |= PCIE_LINK_STATE_L0S;
885881

886882
if (child_lnkctl & PCI_EXP_LNKCTL_ASPM_L0S)
@@ -889,7 +885,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
889885
link->aspm_enabled |= PCIE_LINK_STATE_L0S_DW;
890886

891887
/* Setup L1 state */
892-
if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L1)
888+
if (parent->aspm_l1_support && child->aspm_l1_support)
893889
link->aspm_support |= PCIE_LINK_STATE_L1;
894890

895891
if (parent_lnkctl & child_lnkctl & PCI_EXP_LNKCTL_ASPM_L1)

drivers/pci/probe.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,13 @@ void set_pcie_port_type(struct pci_dev *pdev)
16631663
if (reg32 & PCI_EXP_LNKCAP_DLLLARC)
16641664
pdev->link_active_reporting = 1;
16651665

1666+
#ifdef CONFIG_PCIEASPM
1667+
if (reg32 & PCI_EXP_LNKCAP_ASPM_L0S)
1668+
pdev->aspm_l0s_support = 1;
1669+
if (reg32 & PCI_EXP_LNKCAP_ASPM_L1)
1670+
pdev->aspm_l1_support = 1;
1671+
#endif
1672+
16661673
parent = pci_upstream_bridge(pdev);
16671674
if (!parent)
16681675
return;

include/linux/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ struct pci_dev {
412412
u16 l1ss; /* L1SS Capability pointer */
413413
#ifdef CONFIG_PCIEASPM
414414
struct pcie_link_state *link_state; /* ASPM link state */
415+
unsigned int aspm_l0s_support:1; /* ASPM L0s support */
416+
unsigned int aspm_l1_support:1; /* ASPM L1 support */
415417
unsigned int ltr_path:1; /* Latency Tolerance Reporting
416418
supported from root to here */
417419
#endif

0 commit comments

Comments
 (0)