Re: [PATCH] PCI: Only restore state that was successfully saved around a reset

From: Farhan Ali

Date: Tue Nov 10 2026 - 13:37:07 EST


Hi Li,

On 11/9/2026 9:33 PM, lirongqing wrote:
From: Li RongQing <lirongqing@xxxxxxxxx>

pci_dev_save_and_disable() returns early when config space is inaccessible,
without saving anything, but pci_dev_restore() calls pci_restore_state()
unconditionally and pci_restore_state() does not look at state_saved. After
the reset makes config space accessible again, the all-zero or stale
saved_config_space[] array is written back to the device, clearing Command,
BARs and, for bridges, the bus number registers.

Clear state_saved when the save is skipped and only restore when a state
was saved.

We should always have a valid state of the device saved at enumeration due to commit a2f1e22390ac ("PCI/ERR: Ensure error recoverability at all times"). In pci_dev_save_disable(), if the device is inaccessible then we want to avoid storing a state that can corrupt the device on restore. Since we always have a valid state, we would restore to the last good state.

May I ask what device or driver do you hit this issue?

Thanks

Farhan



Fixes: e18d1abc3bff ("PCI: Avoid saving config space state if inaccessible")
Signed-off-by: Li RongQing <lirongqing@xxxxxxxxx>
---
drivers/pci/pci.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 67fe565..ddb86dd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5156,8 +5156,10 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
*/
pci_set_power_state(dev, PCI_D0);
- if (!pci_dev_config_accessible(dev, "save state"))
+ if (!pci_dev_config_accessible(dev, "save state")) {
+ dev->state_saved = false;
return;
+ }
pci_save_state(dev);
/*
@@ -5175,7 +5177,8 @@ static void pci_dev_restore(struct pci_dev *dev)
const struct pci_error_handlers *err_handler =
dev->driver ? dev->driver->err_handler : NULL;
- pci_restore_state(dev);
+ if (dev->state_saved)
+ pci_restore_state(dev);
/*
* dev->driver->err_handler->reset_done() is protected against