On Tue, Mar 6, 2012 at 6:00 PM, Bjorn Helgaas <bhelgaas@xxxxxxxxxx> wrote: > Normal PCI enumeration via PCI config space uses __pci_read_base(), where > the PCI core applies any bus-to-resource offset. But sparc doesn't use > that path when enumerating via the device tree. > > This adds the corresponding bus-to-resource conversion in the paths that > read BAR values from the OF device tree. > > CC: "David S. Miller" <davem@xxxxxxxxxxxxx> > CC: sparclinux@xxxxxxxxxxxxxxx > Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> > --- > arch/sparc/kernel/pci.c | 66 +++++++++++++++++++++-------------------------- > 1 files changed, 29 insertions(+), 37 deletions(-) > > diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c > index 253e8ac..b4fbfe4 100644 > --- a/arch/sparc/kernel/pci.c > +++ b/arch/sparc/kernel/pci.c > @@ -202,6 +202,7 @@ static void pci_parse_of_addrs(struct platform_device *op, > struct device_node *node, > struct pci_dev *dev) > { > + struct pci_bus_region region; > struct resource *op_res; > const u32 *addrs; > int proplen; > @@ -236,10 +237,11 @@ static void pci_parse_of_addrs(struct platform_device *op, > printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); > continue; > } > - res->start = op_res->start; > - res->end = op_res->end; > res->flags = flags; > res->name = pci_name(dev); > + region.start = op_res->start; > + region.end = op_res->end; > + pcibios_bus_to_resource(dev, res, ®ion); I think this piece is incorrect; I can't find any place in the existing code that applies a bus-to-resource conversion to these resources, so I shouldn't be adding one. I posted an updated series that changes this and folds these fixes into the original patches to preserve bisectability. Bjorn > } > } > > @@ -375,13 +377,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) > *last_p = last; > } > > -static void pci_resource_adjust(struct resource *res, > - struct resource *root) > -{ > - res->start += root->start; > - res->end += root->start; > -} > - > /* For PCI bus devices which lack a 'ranges' property we interrogate > * the config space values to set the resources, just like the generic > * Linux PCI probing code does. > @@ -390,7 +385,8 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev, > struct pci_bus *bus, > struct pci_pbm_info *pbm) > { > - struct resource *res; > + struct pci_bus_region region; > + struct resource *res, res2; > u8 io_base_lo, io_limit_lo; > u16 mem_base_lo, mem_limit_lo; > unsigned long base, limit; > @@ -412,11 +408,14 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev, > res = bus->resource[0]; > if (base <= limit) { > res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; > + res2.flags = res->flags; > + region.start = base; > + region.end = limit + 0xfff; > + pcibios_bus_to_resource(dev, &res2, ®ion); > if (!res->start) > - res->start = base; > + res->start = res2.start; > if (!res->end) > - res->end = limit + 0xfff; > - pci_resource_adjust(res, &pbm->io_space); > + res->end = res2.end; > } > > pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); > @@ -428,9 +427,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev, > if (base <= limit) { > res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | > IORESOURCE_MEM); > - res->start = base; > - res->end = limit + 0xfffff; > - pci_resource_adjust(res, &pbm->mem_space); > + region.start = base; > + region.end = limit + 0xfffff; > + pcibios_bus_to_resource(dev, res, ®ion); > } > > pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); > @@ -459,9 +458,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev, > if (base <= limit) { > res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | > IORESOURCE_MEM | IORESOURCE_PREFETCH); > - res->start = base; > - res->end = limit + 0xfffff; > - pci_resource_adjust(res, &pbm->mem_space); > + region.start = base; > + region.end = limit + 0xfffff; > + pcibios_bus_to_resource(dev, res, ®ion); > } > } > > @@ -472,6 +471,7 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev, > struct pci_bus *bus, > struct pci_pbm_info *pbm) > { > + struct pci_bus_region region; > struct resource *res; > u32 first, last; > u8 map; > @@ -479,18 +479,18 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev, > pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map); > apb_calc_first_last(map, &first, &last); > res = bus->resource[0]; > - res->start = (first << 21); > - res->end = (last << 21) + ((1 << 21) - 1); > res->flags = IORESOURCE_IO; > - pci_resource_adjust(res, &pbm->io_space); > + region.start = (first << 21); > + region.end = (last << 21) + ((1 << 21) - 1); > + pcibios_bus_to_resource(dev, res, ®ion); > > pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); > apb_calc_first_last(map, &first, &last); > res = bus->resource[1]; > - res->start = (first << 21); > - res->end = (last << 21) + ((1 << 21) - 1); > res->flags = IORESOURCE_MEM; > - pci_resource_adjust(res, &pbm->mem_space); > + region.start = (first << 21); > + region.end = (last << 21) + ((1 << 21) - 1); > + pcibios_bus_to_resource(dev, res, ®ion); > } > > static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm, > @@ -506,6 +506,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, > struct pci_bus *bus; > const u32 *busrange, *ranges; > int len, i, simba; > + struct pci_bus_region region; > struct resource *res; > unsigned int flags; > u64 size; > @@ -556,8 +557,6 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, > } > i = 1; > for (; len >= 32; len -= 32, ranges += 8) { > - struct resource *root; > - > flags = pci_parse_of_flags(ranges[0]); > size = GET_64BIT(ranges, 6); > if (flags == 0 || size == 0) > @@ -569,7 +568,6 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, > " for bridge %s\n", node->full_name); > continue; > } > - root = &pbm->io_space; > } else { > if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { > printk(KERN_ERR "PCI: too many memory ranges" > @@ -578,18 +576,12 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, > } > res = bus->resource[i]; > ++i; > - root = &pbm->mem_space; > } > > - res->start = GET_64BIT(ranges, 1); > - res->end = res->start + size - 1; > res->flags = flags; > - > - /* Another way to implement this would be to add an of_device > - * layer routine that can calculate a resource for a given > - * range property value in a PCI device. > - */ > - pci_resource_adjust(res, root); > + region.start = GET_64BIT(ranges, 1); > + region.end = region.start + size - 1; > + pcibios_bus_to_resource(dev, res, ®ion); > } > after_ranges: > sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), > -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html