Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <bhelgaas@google.com>
Tested-by: Shawn Lin <shawn.lin@rock-chips.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Link: https://patch.msgid.link/20251110222929.2140564-2-helgaas@kernel.org

+13 -8
+4 -8
drivers/pci/pcie/aspm.c
··· 830 830 static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) 831 831 { 832 832 struct pci_dev *child = link->downstream, *parent = link->pdev; 833 - u32 parent_lnkcap, child_lnkcap; 834 833 u16 parent_lnkctl, child_lnkctl; 835 834 struct pci_bus *linkbus = parent->subordinate; 836 835 ··· 844 845 * If ASPM not supported, don't mess with the clocks and link, 845 846 * bail out now. 846 847 */ 847 - pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap); 848 - pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap); 849 - if (!(parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPMS)) 848 + if (!(parent->aspm_l0s_support && child->aspm_l0s_support) && 849 + !(parent->aspm_l1_support && child->aspm_l1_support)) 850 850 return; 851 851 852 852 /* Configure common clock before checking latencies */ ··· 857 859 * read-only Link Capabilities may change depending on common clock 858 860 * configuration (PCIe r5.0, sec 7.5.3.6). 859 861 */ 860 - pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap); 861 - pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap); 862 862 pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl); 863 863 pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl); 864 864 ··· 876 880 * given link unless components on both sides of the link each 877 881 * support L0s. 878 882 */ 879 - if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L0S) 883 + if (parent->aspm_l0s_support && child->aspm_l0s_support) 880 884 link->aspm_support |= PCIE_LINK_STATE_L0S; 881 885 882 886 if (child_lnkctl & PCI_EXP_LNKCTL_ASPM_L0S) ··· 885 889 link->aspm_enabled |= PCIE_LINK_STATE_L0S_DW; 886 890 887 891 /* Setup L1 state */ 888 - if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L1) 892 + if (parent->aspm_l1_support && child->aspm_l1_support) 889 893 link->aspm_support |= PCIE_LINK_STATE_L1; 890 894 891 895 if (parent_lnkctl & child_lnkctl & PCI_EXP_LNKCTL_ASPM_L1)
+7
drivers/pci/probe.c
··· 1663 1663 if (reg32 & PCI_EXP_LNKCAP_DLLLARC) 1664 1664 pdev->link_active_reporting = 1; 1665 1665 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 + 1666 1673 parent = pci_upstream_bridge(pdev); 1667 1674 if (!parent) 1668 1675 return;
+2
include/linux/pci.h
··· 412 412 u16 l1ss; /* L1SS Capability pointer */ 413 413 #ifdef CONFIG_PCIEASPM 414 414 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 */ 415 417 unsigned int ltr_path:1; /* Latency Tolerance Reporting 416 418 supported from root to here */ 417 419 #endif