Commit d2f54d9b authored by Bjorn Helgaas's avatar Bjorn Helgaas

PCI: Prevent bus conflicts while checking for bridge apertures

pci_bridge_check_ranges() determines whether the bridge supports an I/O
aperture and a prefetchable memory aperture.

Previously, if the I/O aperture was unsupported, disabled, or configured at
[io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which,
if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff].
The enabled aperture may conflict with other devices in the system.

Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and
PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at
[mem 0xfff00000-0xffffffff], and that may also conflict with other devices.

All we need to know is whether the base and limit registers are writable,
so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE =
0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0,
PCI_PREF_MEMORY_LIMIT = 0xffe0.

Writing non-zero values to both the base and limit registers means we
detect whether either or both are writable, as we did before.
Reported-by: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Based-on-patch-by: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent ac8344c4
...@@ -665,21 +665,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) ...@@ -665,21 +665,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
pci_read_config_word(bridge, PCI_IO_BASE, &io); pci_read_config_word(bridge, PCI_IO_BASE, &io);
if (!io) { if (!io) {
pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
pci_read_config_word(bridge, PCI_IO_BASE, &io); pci_read_config_word(bridge, PCI_IO_BASE, &io);
pci_write_config_word(bridge, PCI_IO_BASE, 0x0); pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
} }
if (io) if (io)
b_res[0].flags |= IORESOURCE_IO; b_res[0].flags |= IORESOURCE_IO;
/* DECchip 21050 pass 2 errata: the bridge may miss an address /* DECchip 21050 pass 2 errata: the bridge may miss an address
disconnect boundary by one PCI data phase. disconnect boundary by one PCI data phase.
Workaround: do not use prefetching on this device. */ Workaround: do not use prefetching on this device. */
if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
return; return;
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
if (!pmem) { if (!pmem) {
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
0xfff0fff0); 0xffe0fff0);
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment