Date: Fri, 12 Jun 2020 07:25:40 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r362087 - stable/12/sys/dev/pci Message-ID: <202006120725.05C7Pe4M050061@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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)); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006120725.05C7Pe4M050061>