aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/pci.c')
-rw-r--r--arch/sparc/kernel/pci.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 539babf00bb2..b36365f49478 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -432,6 +432,11 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
432 node->full_name); 432 node->full_name);
433 return; 433 return;
434 } 434 }
435
436 if (ofpci_verbose)
437 printk(" Bridge bus range [%u --> %u]\n",
438 busrange[0], busrange[1]);
439
435 ranges = of_get_property(node, "ranges", &len); 440 ranges = of_get_property(node, "ranges", &len);
436 simba = 0; 441 simba = 0;
437 if (ranges == NULL) { 442 if (ranges == NULL) {
@@ -451,6 +456,10 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
451 pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); 456 pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
452 bus->bridge_ctl = 0; 457 bus->bridge_ctl = 0;
453 458
459 if (ofpci_verbose)
460 printk(" Bridge ranges[%p] simba[%d]\n",
461 ranges, simba);
462
454 /* parse ranges property, or cook one up by hand for Simba */ 463 /* parse ranges property, or cook one up by hand for Simba */
455 /* PCI #address-cells == 3 and #size-cells == 2 always */ 464 /* PCI #address-cells == 3 and #size-cells == 2 always */
456 res = &dev->resource[PCI_BRIDGE_RESOURCES]; 465 res = &dev->resource[PCI_BRIDGE_RESOURCES];
@@ -468,10 +477,29 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
468 } 477 }
469 i = 1; 478 i = 1;
470 for (; len >= 32; len -= 32, ranges += 8) { 479 for (; len >= 32; len -= 32, ranges += 8) {
480 u64 start;
481
482 if (ofpci_verbose)
483 printk(" RAW Range[%08x:%08x:%08x:%08x:%08x:%08x:"
484 "%08x:%08x]\n",
485 ranges[0], ranges[1], ranges[2], ranges[3],
486 ranges[4], ranges[5], ranges[6], ranges[7]);
487
471 flags = pci_parse_of_flags(ranges[0]); 488 flags = pci_parse_of_flags(ranges[0]);
472 size = GET_64BIT(ranges, 6); 489 size = GET_64BIT(ranges, 6);
473 if (flags == 0 || size == 0) 490 if (flags == 0 || size == 0)
474 continue; 491 continue;
492
493 /* On PCI-Express systems, PCI bridges that have no devices downstream
494 * have a bogus size value where the first 32-bit cell is 0xffffffff.
495 * This results in a bogus range where start + size overflows.
496 *
497 * Just skip these otherwise the kernel will complain when the resource
498 * tries to be claimed.
499 */
500 if (size >> 32 == 0xffffffff)
501 continue;
502
475 if (flags & IORESOURCE_IO) { 503 if (flags & IORESOURCE_IO) {
476 res = bus->resource[0]; 504 res = bus->resource[0];
477 if (res->flags) { 505 if (res->flags) {
@@ -490,8 +518,13 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
490 } 518 }
491 519
492 res->flags = flags; 520 res->flags = flags;
493 region.start = GET_64BIT(ranges, 1); 521 region.start = start = GET_64BIT(ranges, 1);
494 region.end = region.start + size - 1; 522 region.end = region.start + size - 1;
523
524 if (ofpci_verbose)
525 printk(" Using flags[%08x] start[%016llx] size[%016llx]\n",
526 flags, start, size);
527
495 pcibios_bus_to_resource(dev->bus, res, &region); 528 pcibios_bus_to_resource(dev->bus, res, &region);
496 } 529 }
497after_ranges: 530after_ranges:
@@ -584,6 +617,36 @@ static void pci_bus_register_of_sysfs(struct pci_bus *bus)
584 pci_bus_register_of_sysfs(child_bus); 617 pci_bus_register_of_sysfs(child_bus);
585} 618}
586 619
620static void pci_claim_bus_resources(struct pci_bus *bus)
621{
622 struct pci_bus *child_bus;
623 struct pci_dev *dev;
624
625 list_for_each_entry(dev, &bus->devices, bus_list) {
626 int i;
627
628 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
629 struct resource *r = &dev->resource[i];
630
631 if (r->parent || !r->start || !r->flags)
632 continue;
633
634 if (ofpci_verbose)
635 printk("PCI: Claiming %s: "
636 "Resource %d: %016llx..%016llx [%x]\n",
637 pci_name(dev), i,
638 (unsigned long long)r->start,
639 (unsigned long long)r->end,
640 (unsigned int)r->flags);
641
642 pci_claim_resource(dev, i);
643 }
644 }
645
646 list_for_each_entry(child_bus, &bus->children, node)
647 pci_claim_bus_resources(child_bus);
648}
649
587struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, 650struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
588 struct device *parent) 651 struct device *parent)
589{ 652{
@@ -614,6 +677,8 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
614 pci_bus_add_devices(bus); 677 pci_bus_add_devices(bus);
615 pci_bus_register_of_sysfs(bus); 678 pci_bus_register_of_sysfs(bus);
616 679
680 pci_claim_bus_resources(bus);
681
617 return bus; 682 return bus;
618} 683}
619 684