In order to unify suspend and hibernate codepaths without code duplication
the common code should be in common helpers.  Move it from
pci_pm_suspend_noirq() into a helper.  No intended functional changes.

Tested-by: Eric Naim <dn...@cachyos.org>
Signed-off-by: Mario Limonciello (AMD) <supe...@kernel.org>
---
v5:
 * Split from earlier patches
 * Add tags
v4:
 * 
https://lore.kernel.org/linux-pci/20250616175019.3471583-1-supe...@kernel.org/
---
 drivers/pci/pci-driver.c | 81 +++++++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f201d298d7173..571a3809f163a 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -762,6 +762,54 @@ static void pci_pm_complete(struct device *dev)
 
 #endif /* !CONFIG_PM_SLEEP */
 
+#if defined(CONFIG_SUSPEND)
+/**
+ * pci_pm_suspend_noirq_common
+ * @pci_dev: pci device
+ * @skip_bus_pm: pointer to a boolean indicating whether to skip bus PM
+ *
+ * Prepare the device to go into a low power state by saving state and
+ * deciding whether to skip bus PM.
+ *
+ */
+static void pci_pm_suspend_noirq_common(struct pci_dev *pci_dev, bool 
*skip_bus_pm)
+{
+       if (!pci_dev->state_saved) {
+               pci_save_state(pci_dev);
+
+               /*
+                * If the device is a bridge with a child in D0 below it,
+                * it needs to stay in D0, so check skip_bus_pm to avoid
+                * putting it into a low-power state in that case.
+                */
+               if (!pci_dev->skip_bus_pm && pci_power_manageable(pci_dev))
+                       pci_prepare_to_sleep(pci_dev);
+       }
+
+       pci_dbg(pci_dev, "PCI PM: Sleep power state: %s\n",
+               pci_power_name(pci_dev->current_state));
+
+       if (pci_dev->current_state == PCI_D0) {
+               pci_dev->skip_bus_pm = true;
+               /*
+                * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any
+                * downstream device is in D0, so avoid changing the power state
+                * of the parent bridge by setting the skip_bus_pm flag for it.
+                */
+               if (pci_dev->bus->self)
+                       pci_dev->bus->self->skip_bus_pm = true;
+       }
+
+       if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) {
+               pci_dbg(pci_dev, "PCI PM: Skipped\n");
+               *skip_bus_pm = true;
+               return;
+       }
+
+       pci_pm_set_unknown_state(pci_dev);
+}
+#endif /* CONFIG_SUSPEND */
+
 #ifdef CONFIG_SUSPEND
 static void pcie_pme_root_status_cleanup(struct pci_dev *pci_dev)
 {
@@ -851,6 +899,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       bool skip_bus_pm = false;
 
        if (dev_pm_skip_suspend(dev))
                return 0;
@@ -881,38 +930,10 @@ static int pci_pm_suspend_noirq(struct device *dev)
                }
        }
 
-       if (!pci_dev->state_saved) {
-               pci_save_state(pci_dev);
-
-               /*
-                * If the device is a bridge with a child in D0 below it,
-                * it needs to stay in D0, so check skip_bus_pm to avoid
-                * putting it into a low-power state in that case.
-                */
-               if (!pci_dev->skip_bus_pm && pci_power_manageable(pci_dev))
-                       pci_prepare_to_sleep(pci_dev);
-       }
-
-       pci_dbg(pci_dev, "PCI PM: Suspend power state: %s\n",
-               pci_power_name(pci_dev->current_state));
+       pci_pm_suspend_noirq_common(pci_dev, &skip_bus_pm);
 
-       if (pci_dev->current_state == PCI_D0) {
-               pci_dev->skip_bus_pm = true;
-               /*
-                * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any
-                * downstream device is in D0, so avoid changing the power state
-                * of the parent bridge by setting the skip_bus_pm flag for it.
-                */
-               if (pci_dev->bus->self)
-                       pci_dev->bus->self->skip_bus_pm = true;
-       }
-
-       if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) {
-               pci_dbg(pci_dev, "PCI PM: Skipped\n");
+       if (skip_bus_pm)
                goto Fixup;
-       }
-
-       pci_pm_set_unknown_state(pci_dev);
 
        /*
         * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
-- 
2.43.0


Reply via email to