aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2015-01-15 17:21:50 -0500
committerBjorn Helgaas <bhelgaas@google.com>2015-01-16 11:04:42 -0500
commitce821ef0333fc130154ed3091144a590c1909f4d (patch)
tree1bdae4c16343ae124c6dff2b4b60e4a2a676f2b2
parentb0c568de32bad5dc19722ba90ebe07e358675e51 (diff)
ia64/PCI: Clip bridge windows to fit in upstream windows
Every PCI-PCI bridge window should fit inside an upstream bridge window because orphaned address space is unreachable from the primary side of the upstream bridge. If we inherit invalid bridge windows that overlap an upstream window from firmware, clip them to fit and update the bridge accordingly. [bhelgaas: changelog] Link: https://bugzilla.kernel.org/show_bug.cgi?id=85491 Reported-by: Marek Kordik <kordikmarek@gmail.com> Fixes: 5b28541552ef ("PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources") Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> CC: Tony Luck <tony.luck@intel.com> CC: Fenghua Yu <fenghua.yu@intel.com> CC: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> CC: linux-ia64@vger.kernel.org
-rw-r--r--arch/ia64/pci/pci.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 291a582777cf..900cc93e5409 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -487,45 +487,39 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
487 return 0; 487 return 0;
488} 488}
489 489
490static int is_valid_resource(struct pci_dev *dev, int idx) 490void pcibios_fixup_device_resources(struct pci_dev *dev)
491{ 491{
492 unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; 492 int idx;
493 struct resource *devr = &dev->resource[idx], *busr;
494 493
495 if (!dev->bus) 494 if (!dev->bus)
496 return 0; 495 return;
497
498 pci_bus_for_each_resource(dev->bus, busr, i) {
499 if (!busr || ((busr->flags ^ devr->flags) & type_mask))
500 continue;
501 if ((devr->start) && (devr->start >= busr->start) &&
502 (devr->end <= busr->end))
503 return 1;
504 }
505 return 0;
506}
507 496
508static void pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) 497 for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
509{ 498 struct resource *r = &dev->resource[idx];
510 int i;
511 499
512 for (i = start; i < limit; i++) { 500 if (!r->flags || r->parent || !r->start)
513 if (!dev->resource[i].flags)
514 continue; 501 continue;
515 if ((is_valid_resource(dev, i)))
516 pci_claim_resource(dev, i);
517 }
518}
519 502
520void pcibios_fixup_device_resources(struct pci_dev *dev) 503 pci_claim_resource(dev, idx);
521{ 504 }
522 pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
523} 505}
524EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources); 506EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
525 507
526static void pcibios_fixup_bridge_resources(struct pci_dev *dev) 508static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
527{ 509{
528 pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES); 510 int idx;
511
512 if (!dev->bus)
513 return;
514
515 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
516 struct resource *r = &dev->resource[idx];
517
518 if (!r->flags || r->parent || !r->start)
519 continue;
520
521 pci_claim_bridge_resource(dev, idx);
522 }
529} 523}
530 524
531/* 525/*