PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
9d265124d0
and15a260d53f
added quirks for P2P bridges that support I/O windows that start/end at 1K boundaries, not just the 4K boundaries defined by the PCI spec. For details, see the IOBL_ADR register and the EN1K bit in the CNF register in the Intel 82870P2 (P64H2). These quirks complicate the code that reads P2P bridge windows (pci_read_bridge_io() and pci_cfg_fake_ranges()) because the bridge I/O resource is updated in the HEADER quirk, in pci_read_bridge_io(), in pci_setup_bridge(), and again in the FINAL quirk. This is confusing and makes it impossible to reassign the bridge windows after FINAL quirks are run. This patch adds support for 1K windows in the generic paths, so the HEADER quirk only has to enable this support. The FINAL quirk, which used to undo damage done by pci_setup_bridge(), is no longer needed. This removes "if (!res->start) res->start = ..." from pci_read_bridge_io(); that was part of9d265124d0
to avoid overwriting the resource filled in by the quirk. Since pci_read_bridge_io() itself now knows about granularity, the quirk no longer updates the resource and this test is no longer needed. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
@@ -269,15 +269,23 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
|
||||
{
|
||||
struct pci_dev *dev = child->self;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
unsigned long base, limit;
|
||||
unsigned long io_mask, io_granularity, base, limit;
|
||||
struct pci_bus_region region;
|
||||
struct resource *res, res2;
|
||||
struct resource *res;
|
||||
|
||||
io_mask = PCI_IO_RANGE_MASK;
|
||||
io_granularity = 0x1000;
|
||||
if (dev->io_window_1k) {
|
||||
/* Support 1K I/O space granularity */
|
||||
io_mask = PCI_IO_1K_RANGE_MASK;
|
||||
io_granularity = 0x400;
|
||||
}
|
||||
|
||||
res = child->resource[0];
|
||||
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
|
||||
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
|
||||
base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
base = (io_base_lo & io_mask) << 8;
|
||||
limit = (io_limit_lo & io_mask) << 8;
|
||||
|
||||
if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
|
||||
u16 io_base_hi, io_limit_hi;
|
||||
@@ -289,14 +297,9 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
|
||||
|
||||
if (base <= limit) {
|
||||
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
|
||||
res2.flags = res->flags;
|
||||
region.start = base;
|
||||
region.end = limit + 0xfff;
|
||||
pcibios_bus_to_resource(dev, &res2, ®ion);
|
||||
if (!res->start)
|
||||
res->start = res2.start;
|
||||
if (!res->end)
|
||||
res->end = res2.end;
|
||||
region.end = limit + io_granularity - 1;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user