--- /dev/null
+From 7507eb3e7bfac7c3baef8dd377fdf5871eefd42b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= <ilpo.jarvinen@linux.intel.com>
+Date: Fri, 31 Jan 2025 17:29:13 +0200
+Subject: PCI/ASPM: Fix L1SS saving
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+commit 7507eb3e7bfac7c3baef8dd377fdf5871eefd42b upstream.
+
+Commit 1db806ec06b7 ("PCI/ASPM: Save parent L1SS config in
+pci_save_aspm_l1ss_state()") aimed to perform L1SS config save for both the
+Upstream Port and its upstream bridge when handling an Upstream Port, which
+matches what the L1SS restore side does. However, parent->state_saved can
+be set true at an earlier time when the upstream bridge saved other parts
+of its state. Then later when attempting to save the L1SS config while
+handling the Upstream Port, parent->state_saved is true in
+pci_save_aspm_l1ss_state() resulting in early return and skipping saving
+bridge's L1SS config because it is assumed to be already saved. Later on
+restore, junk is written into L1SS config which causes issues with some
+devices.
+
+Remove parent->state_saved check and unconditionally save L1SS config also
+for the upstream bridge from an Upstream Port which ought to be harmless
+from correctness point of view. With the Upstream Port check now present,
+saving the L1SS config more than once for the bridge is no longer a problem
+(unlike when the parent->state_saved check got introduced into the fix
+during its development).
+
+Link: https://lore.kernel.org/r/20250131152913.2507-1-ilpo.jarvinen@linux.intel.com
+Fixes: 1db806ec06b7 ("PCI/ASPM: Save parent L1SS config in pci_save_aspm_l1ss_state()")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219731
+Reported-by: Niklāvs Koļesņikovs <pinkflames.linux@gmail.com>
+Reported by: Rafael J. Wysocki <rafael@kernel.org>
+Closes: https://lore.kernel.org/r/CAJZ5v0iKmynOQ5vKSQbg1J_FmavwZE-nRONovOZ0mpMVauheWg@mail.gmail.com
+Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Closes: https://lore.kernel.org/r/d7246feb-4f3f-4d0c-bb64-89566b170671@molgen.mpg.de
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Niklāvs Koļesņikovs <pinkflames.linux@gmail.com>
+Tested-by: Paul Menzel <pmenzel@molgen.mpg.de> # Dell XPS 13 9360
+Cc: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pcie/aspm.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -108,9 +108,6 @@ void pci_save_aspm_l1ss_state(struct pci
+ pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cap++);
+ pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, cap++);
+
+- if (parent->state_saved)
+- return;
+-
+ /*
+ * Save parent's L1 substate configuration so we have it for
+ * pci_restore_aspm_l1ss_state(pdev) to restore.
--- /dev/null
+From 1db806ec06b7c6e08e8af57088da067963ddf117 Mon Sep 17 00:00:00 2001
+From: Jian-Hong Pan <jhp@endlessos.org>
+Date: Fri, 15 Nov 2024 15:22:02 +0800
+Subject: PCI/ASPM: Save parent L1SS config in pci_save_aspm_l1ss_state()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jian-Hong Pan <jhp@endlessos.org>
+
+commit 1db806ec06b7c6e08e8af57088da067963ddf117 upstream.
+
+After 17423360a27a ("PCI/ASPM: Save L1 PM Substates Capability for
+suspend/resume"), pci_save_aspm_l1ss_state(dev) saves the L1SS state for
+"dev", and pci_restore_aspm_l1ss_state(dev) restores the state for both
+"dev" and its parent.
+
+The problem is that unless pci_save_state() has been used in some other
+path and has already saved the parent L1SS state, we will restore junk to
+the parent, which means the L1 Substates likely won't work correctly.
+
+Save the L1SS config for both the device and its parent in
+pci_save_aspm_l1ss_state(). When restoring, we need both because L1SS must
+be enabled at the parent (the Downstream Port) before being enabled at the
+child (the Upstream Port).
+
+Link: https://lore.kernel.org/r/20241115072200.37509-3-jhp@endlessos.org
+Fixes: 17423360a27a ("PCI/ASPM: Save L1 PM Substates Capability for suspend/resume")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218394
+Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Jian-Hong Pan <jhp@endlessos.org>
+[bhelgaas: parallel save/restore structure, simplify commit log, patch at
+https://lore.kernel.org/r/20241212230340.GA3267194@bhelgaas]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Jian-Hong Pan <jhp@endlessos.org> # Asus B1400CEAE
+Cc: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pcie/aspm.c | 33 ++++++++++++++++++++++++++++-----
+ 1 file changed, 28 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -81,24 +81,47 @@ void pci_configure_aspm_l1ss(struct pci_
+
+ void pci_save_aspm_l1ss_state(struct pci_dev *pdev)
+ {
++ struct pci_dev *parent = pdev->bus->self;
+ struct pci_cap_saved_state *save_state;
+- u16 l1ss = pdev->l1ss;
+ u32 *cap;
+
+ /*
++ * If this is a Downstream Port, we never restore the L1SS state
++ * directly; we only restore it when we restore the state of the
++ * Upstream Port below it.
++ */
++ if (pcie_downstream_port(pdev) || !parent)
++ return;
++
++ if (!pdev->l1ss || !parent->l1ss)
++ return;
++
++ /*
+ * Save L1 substate configuration. The ASPM L0s/L1 configuration
+ * in PCI_EXP_LNKCTL_ASPMC is saved by pci_save_pcie_state().
+ */
+- if (!l1ss)
++ save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_L1SS);
++ if (!save_state)
+ return;
+
+- save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_L1SS);
++ cap = &save_state->cap.data[0];
++ pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cap++);
++ pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, cap++);
++
++ if (parent->state_saved)
++ return;
++
++ /*
++ * Save parent's L1 substate configuration so we have it for
++ * pci_restore_aspm_l1ss_state(pdev) to restore.
++ */
++ save_state = pci_find_saved_ext_cap(parent, PCI_EXT_CAP_ID_L1SS);
+ if (!save_state)
+ return;
+
+ cap = &save_state->cap.data[0];
+- pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL2, cap++);
+- pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, cap++);
++ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, cap++);
++ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, cap++);
+ }
+
+ void pci_restore_aspm_l1ss_state(struct pci_dev *pdev)