PCI: Drop unnecessary retries when restoring BARs

In 2012, commit 26f41062f2 ("PCI: check for pci bar restore completion
and retry") amended pci_restore_state() to attempt BAR restoration up to 10
times.  This was necessary because back in the day, only a 100 msec delay
was observed after pcie_flr() carried out a Function Level Reset.  The
retries ensured that BARs were restored even if devices needed more time to
come out of reset.

In 2016, commit 5adecf817d ("PCI: Wait for up to 1000ms after FLR reset")
extended the delay to 1 sec.  Commit a2758b6b8f ("PCI: Rename
pci_flr_wait() to pci_dev_wait() and make it generic") subsequently
extended it further to 60 sec.

The lengthened delay makes it unnecessary to retry BAR restoration, so
drop it.

Reported-by: Bjorn Helgaas <bhelgaas@google.com>
Closes: https://lore.kernel.org/r/20260416225745.GA41850@bhelgaas/
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/785c98b50a7a00d0698848c75d51b8f5669ad18f.1777814679.git.lukas@wunner.de
This commit is contained in:
Lukas Wunner 2026-05-03 15:34:46 +02:00 committed by Bjorn Helgaas
parent 41167a1e98
commit 10baa9b4df

View File

@ -1784,7 +1784,7 @@ int pci_save_state(struct pci_dev *dev)
EXPORT_SYMBOL(pci_save_state);
static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
u32 saved_val, int retry, bool force)
u32 saved_val, bool force)
{
u32 val;
@ -1792,52 +1792,42 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
if (!force && val == saved_val)
return;
for (;;) {
pci_dbg(pdev, "restore config %#04x: %#010x -> %#010x\n",
offset, val, saved_val);
pci_write_config_dword(pdev, offset, saved_val);
if (retry-- <= 0)
return;
pci_dbg(pdev, "restore config %#04x: %#010x -> %#010x\n", offset, val,
saved_val);
pci_read_config_dword(pdev, offset, &val);
if (val == saved_val)
return;
mdelay(1);
}
pci_write_config_dword(pdev, offset, saved_val);
}
static void pci_restore_config_space_range(struct pci_dev *pdev,
int start, int end, int retry,
bool force)
int start, int end, bool force)
{
int index;
for (index = end; index >= start; index--)
pci_restore_config_dword(pdev, 4 * index,
pdev->saved_config_space[index],
retry, force);
force);
}
static void pci_restore_config_space(struct pci_dev *pdev)
{
if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
pci_restore_config_space_range(pdev, 10, 15, 0, false);
pci_restore_config_space_range(pdev, 10, 15, false);
/* Restore BARs before the command register. */
pci_restore_config_space_range(pdev, 4, 9, 10, false);
pci_restore_config_space_range(pdev, 0, 3, 0, false);
pci_restore_config_space_range(pdev, 4, 9, false);
pci_restore_config_space_range(pdev, 0, 3, false);
} else if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_restore_config_space_range(pdev, 12, 15, 0, false);
pci_restore_config_space_range(pdev, 12, 15, false);
/*
* Force rewriting of prefetch registers to avoid S3 resume
* issues on Intel PCI bridges that occur when these
* registers are not explicitly written.
*/
pci_restore_config_space_range(pdev, 9, 11, 0, true);
pci_restore_config_space_range(pdev, 0, 8, 0, false);
pci_restore_config_space_range(pdev, 9, 11, true);
pci_restore_config_space_range(pdev, 0, 8, false);
} else {
pci_restore_config_space_range(pdev, 0, 15, 0, false);
pci_restore_config_space_range(pdev, 0, 15, false);
}
}