On Tue, Nov 28, 2017 at 02:41:14PM -0600, Bjorn Helgaas wrote: [...] > > +static int cdns_pcie_parse_request_of_pci_ranges(struct device *dev, > > + struct list_head *resources, > > + struct resource **bus_range) > > +{ > > + int err, res_valid = 0; > > + struct device_node *np = dev->of_node; > > + resource_size_t iobase; > > + struct resource_entry *win, *tmp; > > + > > + err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); > > + if (err) > > + return err; > > + > > + err = devm_request_pci_bus_resources(dev, resources); > > + if (err) > > + return err; > > + > > + resource_list_for_each_entry_safe(win, tmp, resources) { > > + struct resource *res = win->res; > > + > > + switch (resource_type(res)) { > > + case IORESOURCE_IO: > > + err = pci_remap_iospace(res, iobase); > > + if (err) { > > + dev_warn(dev, "error %d: failed to map resource %pR\n", > > + err, res); > > + resource_list_destroy_entry(win); > > + } > > + break; > > + case IORESOURCE_MEM: > > + res_valid |= !(res->flags & IORESOURCE_PREFETCH); > > + break; > > + case IORESOURCE_BUS: > > + *bus_range = res; > > + break; > > + } > > + } > > + > > + if (res_valid) > > + return 0; > > + > > + dev_err(dev, "non-prefetchable memory resource required\n"); > > + return -EINVAL; > > +} > > The code above is starting to look awfully familiar. I wonder if it's > time to think about some PCI-internal interface that can encapsulate > this. In this case, there's really nothing Cadence-specific here. > There are other callers where there *is* vendor-specific code, but > possibly that could be handled by returning pointers to bus number, > I/O port, and MMIO resources so the caller could do the > vendor-specific stuff? Yes and that's not the only one, pattern below is duplicated (with some minor differences across host bridges that I think can be managed through function parameters), it is probably worth moving them both into a core code helper. list_splice_init(&resources, &bridge->windows); bridge->dev.parent = dev; bridge->busnr = bus; bridge->ops = &pci_ops; bridge->map_irq = of_irq_parse_and_map_pci; bridge->swizzle_irq = pci_common_swizzle; ret = pci_scan_root_bus_bridge(bridge); if (ret < 0) { dev_err(dev, "Scanning root bridge failed"); goto err_init; } bus = bridge->bus; pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); list_for_each_entry(child, &bus->children, node) pcie_bus_configure_settings(child); pci_bus_add_devices(bus);