aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2013-11-27 17:31:07 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-12-13 10:44:30 -0500
commitd2f54d9b3ee32bc006a7ff25d716b32feba4b522 (patch)
treedad880f706614e9d772f658923c6ae844d374b16 /drivers/pci/setup-bus.c
parentac8344c4c0bf74c7efaf962cf2a6404331678ce4 (diff)
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: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Based-on-patch-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 219a4106480a..80350299a6ea 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -665,21 +665,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
665 665
666 pci_read_config_word(bridge, PCI_IO_BASE, &io); 666 pci_read_config_word(bridge, PCI_IO_BASE, &io);
667 if (!io) { 667 if (!io) {
668 pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); 668 pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
669 pci_read_config_word(bridge, PCI_IO_BASE, &io); 669 pci_read_config_word(bridge, PCI_IO_BASE, &io);
670 pci_write_config_word(bridge, PCI_IO_BASE, 0x0); 670 pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
671 } 671 }
672 if (io) 672 if (io)
673 b_res[0].flags |= IORESOURCE_IO; 673 b_res[0].flags |= IORESOURCE_IO;
674
674 /* DECchip 21050 pass 2 errata: the bridge may miss an address 675 /* DECchip 21050 pass 2 errata: the bridge may miss an address
675 disconnect boundary by one PCI data phase. 676 disconnect boundary by one PCI data phase.
676 Workaround: do not use prefetching on this device. */ 677 Workaround: do not use prefetching on this device. */
677 if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) 678 if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
678 return; 679 return;
680
679 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); 681 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
680 if (!pmem) { 682 if (!pmem) {
681 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 683 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
682 0xfff0fff0); 684 0xffe0fff0);
683 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); 685 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
684 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); 686 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
685 } 687 }