Re: [PATCH v3 2/3] PCI/PM: Run bridge power up actions as part of restore phase
From: Rafael J. Wysocki (Intel)
Date: Fri Sep 04 2026 - 10:54:40 EST
On Fri, Sep 4, 2026 at 3:09 PM Rafael J. Wysocki (Intel)
<rafael@xxxxxxxxxx> wrote:
>
> On Mon, Aug 31, 2026 at 10:56 PM Mario Limonciello
> <mario.limonciello@xxxxxxx> wrote:
> >
> > From: "Mario Limonciello (AMD)" <superm1@xxxxxxxxxx>
> >
> > pci_pm_resume_noirq() calls pci_pm_bridge_power_up_actions() when a
> > bridge is coming back from D3cold and bus PM was not skipped, so that
> > the mandatory post-power-on link training delays are observed before
> > any downstream device is accessed.
> >
> > The last patch in this series makes the hibernate poweroff_noirq path
> > put bridges with downstream devices into D3 (including D3cold),
> > mirroring what the S3 suspend path already does. For that to be safe,
> > the hibernate image restore path has to bring those bridges back up the
> > same way suspend resume does; otherwise a downstream device may be
> > accessed before its parent bridge's link is retrained.
>
> Note though that pci_pm_restore_noirq() runs after the boot kernel has
> initialized the PCI bus, so all of the links should be retrained by
> that time.
>
> It then carries out a "freeze" transition before passing control to
s/It then/The boot kernel/
> the image kernel, so "restore" doesn't really get devices in
> "pristine" states.
>
> Moreover, BIOS code runs before "poweroff_noirq" and the boot kernel
s/before/between/
> and it also messes up with devices in general.
Sent too early, sorry about that, but the question below is still relevant.
> Is there a specific issue that is avoided by this change?
>
> > Add the same bridge power up actions to pci_pm_restore_noirq(), gated on
> > the same conditions as the resume path (bus PM not skipped and the
> > previous state being D3cold), so that hibernate restore and suspend
> > resume behave identically for bridges.
> >
> > Tested-by: Eric Naim <dnaim@xxxxxxxxxxx>
> > Signed-off-by: Mario Limonciello (AMD) <superm1@xxxxxxxxxx>
> > ---
> > drivers/pci/pci-driver.c | 5 +++++
> > 1 file changed, 5 insertions(+)
> >
> > diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> > index e3d352c7b31d4..d15b3eb55ec53 100644
> > --- a/drivers/pci/pci-driver.c
> > +++ b/drivers/pci/pci-driver.c
> > @@ -1297,10 +1297,15 @@ static int pci_pm_restore_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;
> > + pci_power_t prev_state = pci_dev->current_state;
> > + bool skip_bus_pm = pci_dev->skip_bus_pm;
> >
> > pci_pm_default_resume_early(pci_dev);
> > pci_fixup_device(pci_fixup_resume_early, pci_dev);
> >
> > + if (!skip_bus_pm && prev_state == PCI_D3cold)
> > + pci_pm_bridge_power_up_actions(pci_dev);
> > +
> > if (pci_has_legacy_pm_support(pci_dev))
> > return 0;
> >
> > --
> > 2.43.0
> >