From 93a6423bd84d977bd768a001c6c3868e6a20b63a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Aug 2014 23:22:39 -0700 Subject: sparc64: Expand PCI bridge probing debug logging. Dump the various aspects of the PCI bridge probed at boot time, most importantly the bridge number ranges, and the ranges property. This helps diagnose PCI resource issues and other problems by giving ofpci_debug=1 on the boot command line. Signed-off-by: David S. Miller --- arch/sparc/kernel/pci.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'arch/sparc/kernel/pci.c') diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 539babf00bb..da24fb6deb0 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, node->full_name); return; } + + if (ofpci_verbose) + printk(" Bridge bus range [%u --> %u]\n", + busrange[0], busrange[1]); + ranges = of_get_property(node, "ranges", &len); simba = 0; if (ranges == NULL) { @@ -451,6 +456,10 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; + if (ofpci_verbose) + printk(" Bridge ranges[%p] simba[%d]\n", + ranges, simba); + /* parse ranges property, or cook one up by hand for Simba */ /* PCI #address-cells == 3 and #size-cells == 2 always */ res = &dev->resource[PCI_BRIDGE_RESOURCES]; @@ -468,6 +477,14 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, } i = 1; for (; len >= 32; len -= 32, ranges += 8) { + u64 start; + + if (ofpci_verbose) + printk(" RAW Range[%08x:%08x:%08x:%08x:%08x:%08x:" + "%08x:%08x]\n", + ranges[0], ranges[1], ranges[2], ranges[3], + ranges[4], ranges[5], ranges[6], ranges[7]); + flags = pci_parse_of_flags(ranges[0]); size = GET_64BIT(ranges, 6); if (flags == 0 || size == 0) @@ -490,8 +507,13 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, } res->flags = flags; - region.start = GET_64BIT(ranges, 1); + region.start = start = GET_64BIT(ranges, 1); region.end = region.start + size - 1; + + if (ofpci_verbose) + printk(" Using flags[%08x] start[%016llx] size[%016llx]\n", + flags, start, size); + pcibios_bus_to_resource(dev->bus, res, ®ion); } after_ranges: -- cgit v1.2.3-70-g09d2 From 4afba24e5fc2626a3c604ec990539572f6662ff9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Aug 2014 23:27:01 -0700 Subject: sparc64: Skip bogus PCI bridge ranges. It seems that when a PCI Express bridge is not in use and has no devices behind it, the ranges property is bogus. Specifically the size property is of the form [0xffffffff:...], and if you add this size to the resource start address the 64-bit calculation will overflow. Just check specifically for this size value signature and skip them. Signed-off-by: David S. Miller --- arch/sparc/kernel/pci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/sparc/kernel/pci.c') diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index da24fb6deb0..cc4c31e5185 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -489,6 +489,17 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, size = GET_64BIT(ranges, 6); if (flags == 0 || size == 0) continue; + + /* On PCI-Express systems, PCI bridges that have no devices downstream + * have a bogus size value where the first 32-bit cell is 0xffffffff. + * This results in a bogus range where start + size overflows. + * + * Just skip these otherwise the kernel will complain when the resource + * tries to be claimed. + */ + if (size >> 32 == 0xffffffff) + continue; + if (flags & IORESOURCE_IO) { res = bus->resource[0]; if (res->flags) { -- cgit v1.2.3-70-g09d2 From f1d25d37d316b8af202e51a4f82df01e12fe2661 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 12 Aug 2014 23:29:09 -0700 Subject: sparc64: Properly claim resources as each PCI bus is probed. Perform a pci_claim_resource() on all valid resources discovered during the OF device tree scan. Based almost entirely upon the PCI OF bus probing code which does the same thing there. Signed-off-by: David S. Miller --- arch/sparc/kernel/pci.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch/sparc/kernel/pci.c') diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index cc4c31e5185..b36365f4947 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -617,6 +617,36 @@ static void pci_bus_register_of_sysfs(struct pci_bus *bus) pci_bus_register_of_sysfs(child_bus); } +static void pci_claim_bus_resources(struct pci_bus *bus) +{ + struct pci_bus *child_bus; + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + + if (ofpci_verbose) + printk("PCI: Claiming %s: " + "Resource %d: %016llx..%016llx [%x]\n", + pci_name(dev), i, + (unsigned long long)r->start, + (unsigned long long)r->end, + (unsigned int)r->flags); + + pci_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &bus->children, node) + pci_claim_bus_resources(child_bus); +} + struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, struct device *parent) { @@ -647,6 +677,8 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_bus_add_devices(bus); pci_bus_register_of_sysfs(bus); + pci_claim_bus_resources(bus); + return bus; } -- cgit v1.2.3-70-g09d2