Author: avg Date: Fri Jun 12 07:25:40 2020 New Revision: 362087 URL: https://svnweb.freebsd.org/changeset/base/362087
Log: MFC r361621: do not enable pci bridge decoding on resume until I/O windows are restored PCI bus driver restores most but not all of a child PCI-PCI bridge configuration. The bridge's I/O windows are restored by pcib driver and that happens later in time. This can be problematic because the Command register is restored before the windows are restored. If the firmware programs the windows incorrectly or even does not program them at all, then the bridge can start claiming I/O cycles that are not intended for it. This will continue until the correct windows are restored. I have observed this problem with a buggy BIOS where after resuming from S3 an I/O port window of a PCI-PCI bridge was configured with zero base and limit causing the bridge to claim 0x0 - 0xFFF port range. That interfered with ACPI port access including ACPI PM Timer at port 0x808, thus wreaking havoc in the time keeping. The solution is to restore the Command register of PCI-PCI bridges after the windows are restored in pcib driver. While here, I decided that for other PCI device types (normal and cardbus) it's better to restore the Command register after their BARs are restored. Modified: stable/12/sys/dev/pci/pci.c stable/12/sys/dev/pci/pci_pci.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/dev/pci/pci.c ============================================================================== --- stable/12/sys/dev/pci/pci.c Fri Jun 12 07:23:27 2020 (r362086) +++ stable/12/sys/dev/pci/pci.c Fri Jun 12 07:25:40 2020 (r362087) @@ -5933,7 +5933,6 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinf */ if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) pci_set_powerstate(dev, PCI_POWERSTATE_D0); - pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2); pci_write_config(dev, PCIR_INTLINE, dinfo->cfg.intline, 1); pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1); pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1); @@ -5971,6 +5970,9 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinf break; } pci_restore_bars(dev); + + if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_BRIDGE) + pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2); /* * Restore extended capabilities for PCI-Express and PCI-X Modified: stable/12/sys/dev/pci/pci_pci.c ============================================================================== --- stable/12/sys/dev/pci/pci_pci.c Fri Jun 12 07:23:27 2020 (r362086) +++ stable/12/sys/dev/pci/pci_pci.c Fri Jun 12 07:25:40 2020 (r362087) @@ -1786,6 +1786,12 @@ pcib_resume(device_t dev) { pcib_cfg_restore(device_get_softc(dev)); + + /* + * Restore the Command register only after restoring the windows. + * The bridge should not be claiming random windows. + */ + pci_write_config(dev, PCIR_COMMAND, pci_get_cmdreg(dev), 2); return (bus_generic_resume(dev)); } _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"