From 2ae535532188b7772c2aba80247dfdce23d8f275 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 13 Nov 2022 20:45:38 +0000 Subject: [pci] Backup and restore standard config space across PCIe FLR The behaviour of PCI devices across a function-level reset seems to be inconsistent in practice: some devices will preserve PCI BARs, some will not. Fix the behaviour of FLR on devices that do not preserve PCI BARs by backing up and restoring PCI configuration space across the reset. Preserve only the standard portion of the configuration space, since there may be registers with unexpected side effects in the remaining non-standardised space. Signed-off-by: Michael Brown --- src/drivers/bus/pciextra.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c index 23617bc9a..1eeb9b2a0 100644 --- a/src/drivers/bus/pciextra.c +++ b/src/drivers/bus/pciextra.c @@ -3,6 +3,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include static int pci_find_capability_common ( struct pci_device *pci, uint8_t pos, int cap ) { @@ -121,8 +122,12 @@ unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) { * @v exp PCI Express Capability address */ void pci_reset ( struct pci_device *pci, unsigned int exp ) { + struct pci_config_backup backup; uint16_t control; + /* Back up configuration space */ + pci_backup ( pci, &backup, PCI_CONFIG_BACKUP_STANDARD, NULL ); + /* Perform a PCIe function-level reset */ pci_read_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), &control ); control |= PCI_EXP_DEVCTL_FLR; @@ -131,6 +136,6 @@ void pci_reset ( struct pci_device *pci, unsigned int exp ) { /* Allow time for reset to complete */ mdelay ( PCI_EXP_FLR_DELAY_MS ); - /* Re-enable device */ - adjust_pci_device ( pci ); + /* Restore configuration */ + pci_restore ( pci, &backup, PCI_CONFIG_BACKUP_STANDARD, NULL ); } -- cgit