aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-07-09 15:38:57 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-07-09 21:52:04 -0400
commit2b28ae1912e5ce5bb0527e352ae6ff04e76183d1 (patch)
treef8fb930ee1277c1e59c3db8bb802867e2c2d9a59 /drivers
parent5dde383e2ef5e22fe7db689dc38c1aabfb801449 (diff)
PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
9d265124d051 and 15a260d53f7c 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 of 9d265124d051 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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/probe.c25
-rw-r--r--drivers/pci/quirks.c39
-rw-r--r--drivers/pci/setup-bus.c11
3 files changed, 24 insertions, 51 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 9c5d2a992999..ef24cf765b2f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -269,15 +269,23 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
269{ 269{
270 struct pci_dev *dev = child->self; 270 struct pci_dev *dev = child->self;
271 u8 io_base_lo, io_limit_lo; 271 u8 io_base_lo, io_limit_lo;
272 unsigned long base, limit; 272 unsigned long io_mask, io_granularity, base, limit;
273 struct pci_bus_region region; 273 struct pci_bus_region region;
274 struct resource *res, res2; 274 struct resource *res;
275
276 io_mask = PCI_IO_RANGE_MASK;
277 io_granularity = 0x1000;
278 if (dev->io_window_1k) {
279 /* Support 1K I/O space granularity */
280 io_mask = PCI_IO_1K_RANGE_MASK;
281 io_granularity = 0x400;
282 }
275 283
276 res = child->resource[0]; 284 res = child->resource[0];
277 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); 285 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
278 pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); 286 pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
279 base = (io_base_lo & PCI_IO_RANGE_MASK) << 8; 287 base = (io_base_lo & io_mask) << 8;
280 limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8; 288 limit = (io_limit_lo & io_mask) << 8;
281 289
282 if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { 290 if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
283 u16 io_base_hi, io_limit_hi; 291 u16 io_base_hi, io_limit_hi;
@@ -289,14 +297,9 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
289 297
290 if (base <= limit) { 298 if (base <= limit) {
291 res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; 299 res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
292 res2.flags = res->flags;
293 region.start = base; 300 region.start = base;
294 region.end = limit + 0xfff; 301 region.end = limit + io_granularity - 1;
295 pcibios_bus_to_resource(dev, &res2, &region); 302 pcibios_bus_to_resource(dev, res, &region);
296 if (!res->start)
297 res->start = res2.start;
298 if (!res->end)
299 res->end = res2.end;
300 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); 303 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
301 } 304 }
302} 305}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 2a7521677541..356846bd7ffb 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1938,53 +1938,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1
1938static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) 1938static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
1939{ 1939{
1940 u16 en1k; 1940 u16 en1k;
1941 u8 io_base_lo, io_limit_lo;
1942 unsigned long base, limit;
1943 struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
1944 1941
1945 pci_read_config_word(dev, 0x40, &en1k); 1942 pci_read_config_word(dev, 0x40, &en1k);
1946 1943
1947 if (en1k & 0x200) { 1944 if (en1k & 0x200) {
1948 dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n"); 1945 dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
1949 1946 dev->io_window_1k = 1;
1950 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
1951 pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
1952 base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
1953 limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
1954
1955 if (base <= limit) {
1956 res->start = base;
1957 res->end = limit + 0x3ff;
1958 }
1959 } 1947 }
1960} 1948}
1961DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); 1949DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
1962 1950
1963/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
1964 * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge()
1965 * in drivers/pci/setup-bus.c
1966 */
1967static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
1968{
1969 u16 en1k, iobl_adr, iobl_adr_1k;
1970 struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
1971
1972 pci_read_config_word(dev, 0x40, &en1k);
1973
1974 if (en1k & 0x200) {
1975 pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr);
1976
1977 iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
1978
1979 if (iobl_adr != iobl_adr_1k) {
1980 dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
1981 iobl_adr,iobl_adr_1k);
1982 pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
1983 }
1984 }
1985}
1986DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl);
1987
1988/* Under some circumstances, AER is not linked with extended capabilities. 1951/* Under some circumstances, AER is not linked with extended capabilities.
1989 * Force it to be linked by setting the corresponding control bit in the 1952 * Force it to be linked by setting the corresponding control bit in the
1990 * config space. 1953 * config space.
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 8fa2d4be88de..dad5425f1f09 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -469,16 +469,23 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
469 struct pci_dev *bridge = bus->self; 469 struct pci_dev *bridge = bus->self;
470 struct resource *res; 470 struct resource *res;
471 struct pci_bus_region region; 471 struct pci_bus_region region;
472 unsigned long io_mask;
473 u8 io_base_lo, io_limit_lo;
472 u32 l, io_upper16; 474 u32 l, io_upper16;
473 475
476 io_mask = PCI_IO_RANGE_MASK;
477 if (bridge->io_window_1k)
478 io_mask = PCI_IO_1K_RANGE_MASK;
479
474 /* Set up the top and bottom of the PCI I/O segment for this bus. */ 480 /* Set up the top and bottom of the PCI I/O segment for this bus. */
475 res = bus->resource[0]; 481 res = bus->resource[0];
476 pcibios_resource_to_bus(bridge, &region, res); 482 pcibios_resource_to_bus(bridge, &region, res);
477 if (res->flags & IORESOURCE_IO) { 483 if (res->flags & IORESOURCE_IO) {
478 pci_read_config_dword(bridge, PCI_IO_BASE, &l); 484 pci_read_config_dword(bridge, PCI_IO_BASE, &l);
479 l &= 0xffff0000; 485 l &= 0xffff0000;
480 l |= (region.start >> 8) & 0x00f0; 486 io_base_lo = (region.start >> 8) & io_mask;
481 l |= region.end & 0xf000; 487 io_limit_lo = (region.end >> 8) & io_mask;
488 l |= ((u32) io_limit_lo << 8) | io_base_lo;
482 /* Set up upper 16 bits of I/O base/limit. */ 489 /* Set up upper 16 bits of I/O base/limit. */
483 io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); 490 io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
484 dev_info(&bridge->dev, " bridge window %pR\n", res); 491 dev_info(&bridge->dev, " bridge window %pR\n", res);