]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
Revert "PCI/ASPM: Remove pcie_aspm_pm_state_change()"
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 1 Jan 2024 18:08:18 +0000 (12:08 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Jan 2024 17:51:08 +0000 (18:51 +0100)
commit f93e71aea6c60ebff8adbd8941e678302d377869 upstream.

This reverts commit 08d0cc5f34265d1a1e3031f319f594bd1970976c.

Michael reported that when attempting to resume from suspend to RAM on ASUS
mini PC PN51-BB757MDE1 (DMI model: MINIPC PN51-E1), 08d0cc5f3426
("PCI/ASPM: Remove pcie_aspm_pm_state_change()") caused a 12-second delay
with no output, followed by a reboot.

Workarounds include:

  - Reverting 08d0cc5f3426 ("PCI/ASPM: Remove pcie_aspm_pm_state_change()")
  - Booting with "pcie_aspm=off"
  - Booting with "pcie_aspm.policy=performance"
  - "echo 0 | sudo tee /sys/bus/pci/devices/0000:03:00.0/link/l1_aspm"
    before suspending
  - Connecting a USB flash drive

Link: https://lore.kernel.org/r/20240102232550.1751655-1-helgaas@kernel.org
Fixes: 08d0cc5f3426 ("PCI/ASPM: Remove pcie_aspm_pm_state_change()")
Reported-by: Michael Schaller <michael@5challer.de>
Link: https://lore.kernel.org/r/76c61361-b8b4-435f-a9f1-32b716763d62@5challer.de
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aspm.c

index cc3f620b73bd752df2ccf3cb3e85b44ffb4a6901..36f1e604191e5fd1ff76f37cdcb353fd28a7787f 100644 (file)
@@ -820,6 +820,9 @@ int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
                        return 1;
        }
 
+       if (dev->bus->self)
+               pcie_aspm_pm_state_change(dev->bus->self);
+
        return 0;
 }
 
@@ -1140,6 +1143,9 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
        if (need_restore)
                pci_restore_bars(dev);
 
+       if (dev->bus->self)
+               pcie_aspm_pm_state_change(dev->bus->self);
+
        return 0;
 }
 
index e6ea6e9504280a0ac06161697e392d1eb28d7547..72280e9b23b25a1cd43a7ddb3b0dfcbf56fec2cb 100644 (file)
@@ -595,10 +595,12 @@ bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
 #ifdef CONFIG_PCIEASPM
 void pcie_aspm_init_link_state(struct pci_dev *pdev);
 void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+void pcie_aspm_pm_state_change(struct pci_dev *pdev);
 void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
 #else
 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { }
 static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { }
+static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { }
 static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { }
 #endif
 
index 233e42ddaa9d541df4a36010531aeedf0f52ba6a..e3f81948ce724a24169c45ce9181387b1d56f3e6 100644 (file)
@@ -1038,6 +1038,25 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
        up_read(&pci_bus_sem);
 }
 
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link = pdev->link_state;
+
+       if (aspm_disabled || !link)
+               return;
+       /*
+        * Devices changed PM state, we should recheck if latency
+        * meets all functions' requirement
+        */
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+       pcie_update_aspm_capable(link->root);
+       pcie_config_aspm_path(link);
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+}
+
 void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
 {
        struct pcie_link_state *link = pdev->link_state;