summaryrefslogtreecommitdiff
path: root/drivers/pci/pcie/aspm.c
diff options
context:
space:
mode:
authorVidya Sagar <vidyas@nvidia.com>2022-09-13 16:18:22 +0300
committerBjorn Helgaas <bhelgaas@google.com>2022-10-05 04:35:40 +0300
commit4ff116d0d5fd8a025604b0802d93a2d5f4e465d1 (patch)
treea9578e55a122e03ebec0354dd08f88a5d1abdf3c /drivers/pci/pcie/aspm.c
parent5e85eba6f50dc288c22083a7e213152bcc4b8208 (diff)
downloadlinux-4ff116d0d5fd8a025604b0802d93a2d5f4e465d1.tar.xz
PCI/ASPM: Save L1 PM Substates Capability for suspend/resume
Previously the L1 PM Substates Control Registers (CTL1 and CTL2) weren't saved and restored during suspend/resume leading to the L1 PM Substates configuration being lost post-resume. Save the L1 PM Substates Control Registers so that the configuration is retained post-resume. [bhelgaas: drop pci_is_pcie() testing; we can rely on pci_configure_ltr() having already done that] Link: https://lore.kernel.org/r/20220913131822.16557-3-vidyas@nvidia.com Signed-off-by: Vidya Sagar <vidyas@nvidia.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r--drivers/pci/pcie/aspm.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index b4bdadc4ac35..016d222b07c7 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -732,6 +732,43 @@ static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
PCI_L1SS_CTL1_L1SS_MASK, val);
}
+void pci_save_aspm_l1ss_state(struct pci_dev *dev)
+{
+ struct pci_cap_saved_state *save_state;
+ u16 l1ss = dev->l1ss;
+ u32 *cap;
+
+ if (!l1ss)
+ return;
+
+ save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_L1SS);
+ if (!save_state)
+ return;
+
+ cap = (u32 *)&save_state->cap.data[0];
+ pci_read_config_dword(dev, l1ss + PCI_L1SS_CTL2, cap++);
+ pci_read_config_dword(dev, l1ss + PCI_L1SS_CTL1, cap++);
+}
+
+void pci_restore_aspm_l1ss_state(struct pci_dev *dev)
+{
+ struct pci_cap_saved_state *save_state;
+ u32 *cap, ctl1, ctl2;
+ u16 l1ss = dev->l1ss;
+
+ if (!l1ss)
+ return;
+
+ save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_L1SS);
+ if (!save_state)
+ return;
+
+ cap = (u32 *)&save_state->cap.data[0];
+ ctl2 = *cap++;
+ ctl1 = *cap;
+ aspm_program_l1ss(dev, ctl1, ctl2);
+}
+
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{
pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,