diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2012-07-10 10:36:09 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-07-10 10:36:09 -0400 |
commit | 6ee53f4c38e70ba34777ad38807a50c1812ff36f (patch) | |
tree | 8a4eeef5923d28c2e4ab14f4559e686cc1fce455 /drivers/pci/probe.c | |
parent | d68e70c6e59ad08feca291c2790164d3231c425e (diff) | |
parent | 1c975931128c1128892981095a64fb8eabf240eb (diff) |
Merge branch 'pci/bjorn-p2p-bridge-windows' into next
* pci/bjorn-p2p-bridge-windows:
sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases()
PCI: support sizing P2P bridge I/O windows with 1K granularity
PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2)
PCI: allow P2P bridge windows starting at PCI bus address zero
Conflicts:
drivers/pci/probe.c
include/linux/pci.h
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5e5358a3dd92..6c143b4497ca 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -306,15 +306,23 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) | |||
306 | { | 306 | { |
307 | struct pci_dev *dev = child->self; | 307 | struct pci_dev *dev = child->self; |
308 | u8 io_base_lo, io_limit_lo; | 308 | u8 io_base_lo, io_limit_lo; |
309 | unsigned long base, limit; | 309 | unsigned long io_mask, io_granularity, base, limit; |
310 | struct pci_bus_region region; | 310 | struct pci_bus_region region; |
311 | struct resource *res, res2; | 311 | struct resource *res; |
312 | |||
313 | io_mask = PCI_IO_RANGE_MASK; | ||
314 | io_granularity = 0x1000; | ||
315 | if (dev->io_window_1k) { | ||
316 | /* Support 1K I/O space granularity */ | ||
317 | io_mask = PCI_IO_1K_RANGE_MASK; | ||
318 | io_granularity = 0x400; | ||
319 | } | ||
312 | 320 | ||
313 | res = child->resource[0]; | 321 | res = child->resource[0]; |
314 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); | 322 | pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); |
315 | pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); | 323 | pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); |
316 | base = (io_base_lo & PCI_IO_RANGE_MASK) << 8; | 324 | base = (io_base_lo & io_mask) << 8; |
317 | limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8; | 325 | limit = (io_limit_lo & io_mask) << 8; |
318 | 326 | ||
319 | if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { | 327 | if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { |
320 | u16 io_base_hi, io_limit_hi; | 328 | u16 io_base_hi, io_limit_hi; |
@@ -325,16 +333,11 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) | |||
325 | limit |= ((unsigned long) io_limit_hi << 16); | 333 | limit |= ((unsigned long) io_limit_hi << 16); |
326 | } | 334 | } |
327 | 335 | ||
328 | if (base && base <= limit) { | 336 | if (base <= limit) { |
329 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; | 337 | res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; |
330 | res2.flags = res->flags; | ||
331 | region.start = base; | 338 | region.start = base; |
332 | region.end = limit + 0xfff; | 339 | region.end = limit + io_granularity - 1; |
333 | pcibios_bus_to_resource(dev, &res2, ®ion); | 340 | pcibios_bus_to_resource(dev, res, ®ion); |
334 | if (!res->start) | ||
335 | res->start = res2.start; | ||
336 | if (!res->end) | ||
337 | res->end = res2.end; | ||
338 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 341 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
339 | } | 342 | } |
340 | } | 343 | } |
@@ -352,7 +355,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) | |||
352 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); | 355 | pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); |
353 | base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; | 356 | base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; |
354 | limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; | 357 | limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; |
355 | if (base && base <= limit) { | 358 | if (base <= limit) { |
356 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; | 359 | res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; |
357 | region.start = base; | 360 | region.start = base; |
358 | region.end = limit + 0xfffff; | 361 | region.end = limit + 0xfffff; |
@@ -399,7 +402,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) | |||
399 | #endif | 402 | #endif |
400 | } | 403 | } |
401 | } | 404 | } |
402 | if (base && base <= limit) { | 405 | if (base <= limit) { |
403 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | | 406 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | |
404 | IORESOURCE_MEM | IORESOURCE_PREFETCH; | 407 | IORESOURCE_MEM | IORESOURCE_PREFETCH; |
405 | if (res->flags & PCI_PREF_RANGE_TYPE_64) | 408 | if (res->flags & PCI_PREF_RANGE_TYPE_64) |