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. To do: per jhb's suggestion, move the window handling to pci driver. Reviewed by: imp, jhb, kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D25028
This commit is contained in:
parent
c44d9a48fc
commit
41c3b8a6ad
@ -5932,7 +5932,6 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
|
||||
*/
|
||||
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 *dinfo)
|
||||
}
|
||||
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
|
||||
*/
|
||||
|
@ -1792,6 +1792,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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user