[PATCH RFC 14/25] PCI/LUO: Restore power state of a PCI device
From: chrisl
Date: Mon Jul 28 2025 - 04:28:38 EST
From: Jason Miu <jasonmiu@xxxxxxxxxx>
>From the liveupdate saved PCI device state, restore the device power
state.
The `pci_dev->current_state` is a cached power state. If the device
driver calls `pci_enable_device()`, this value can be modified from
reading the PMCSR register (see `pci_enable_device_flags()`). In the
future patches when a driver tries to enable the PCI device after
liveupdate, we should check the device power state at that moment with
the saved value.
Tested: QEMU liveupdate boot test. Trigger the liveupdate to the
`finish` phase.
Signed-off-by: Chris Li <chrisl@xxxxxxxxxx>
---
drivers/pci/pci.h | 6 ++++++
drivers/pci/probe.c | 8 ++++++--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 2ef12745ee05960878d8d3fe0cdf136f69c8d408..a8acc986a5aac808ec64395d7d946ee036270f5b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1182,9 +1182,15 @@ static inline int pci_msix_write_tph_tag(struct pci_dev *pdev, unsigned int inde
PCI_CONF1_EXT_REG(reg))
#ifdef CONFIG_LIVEUPDATE
+#define PCI_SER_GET(__pci_dev, __var, __def) \
+ (__pci_dev->dev.lu.dev_state) ? \
+ ((struct pci_dev_ser *)__pci_dev->dev.lu.dev_state)->__var : __def
+
void pci_liveupdate_restore(struct pci_dev *dev);
void pci_liveupdate_override_driver(struct pci_dev *dev);
#else
+#define PCI_SER_GET(__dev, __var, __def) __def
+
static inline void pci_liveupdate_restore(struct pci_dev *dev) {}
static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {}
#endif
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e41a1bef2083aa9184fd1c894d5de964f19d5c01..7dd2cf9f9e110636f8998df22a333638cce25e6b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2030,8 +2030,12 @@ int pci_setup_device(struct pci_dev *dev)
if (pci_is_pcie(dev))
dev->supported_speeds = pcie_get_supported_speeds(dev);
- /* "Unknown power state" */
- dev->current_state = PCI_UNKNOWN;
+ /*
+ * Restore the power state from liveupdate saved state.
+ * If we are not booted from liveupdate, default
+ * "Unknown power state".
+ */
+ dev->current_state = PCI_SER_GET(dev, current_state, PCI_UNKNOWN);
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
--
2.50.1.487.gc89ff58d15-goog