Message ID | PS1PR06MB11801A23491F06B6BE81DB6AF5150@PS1PR06MB1180.apcprd06.prod.outlook.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Bjorn Helgaas |
Headers | show |
On Mon, Nov 09, 2015 at 10:26:39AM +0000, Phil Edworthy wrote: > The main purpose of this change is to avoid calling pci_ioremap_io() as > this is not available on arm64. However, instead of doing the range passing > in this driver we can utilise of_pci_get_host_bridge_resources(). > > This is similar to changes made to the generic PCI host driver in commit > dbf9826d "PCI: generic: Convert to DT resource parsing API". > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> I think the following should be carried over from v1: Reported-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Bjorn, I know there have been a few false starts with regards to recent pcie-rcar changes. But some more rigor has been applied to this one. Please consider applying it. Acked-by: Simon Horman <horms+renesas@verge.net.au> > --- > v2: > - Remove incorrect res_valid check > --- > drivers/pci/host/pcie-rcar.c | 116 +++++++++++++++++++++++++++---------------- > 1 file changed, 73 insertions(+), 43 deletions(-) > > diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c > index 6a3a612..c977fa6 100644 > --- a/drivers/pci/host/pcie-rcar.c > +++ b/drivers/pci/host/pcie-rcar.c > @@ -108,8 +108,6 @@ > #define RCAR_PCI_MAX_RESOURCES 4 > #define MAX_NR_INBOUND_MAPS 6 > > -static unsigned long global_io_offset; > - > struct rcar_msi { > DECLARE_BITMAP(used, INT_PCI_MSI_NR); > struct irq_domain *domain; > @@ -138,8 +136,7 @@ struct rcar_pcie { > #endif > struct device *dev; > void __iomem *base; > - struct resource res[RCAR_PCI_MAX_RESOURCES]; > - struct resource busn; > + struct list_head resources; > int root_bus_nr; > struct clk *clk; > struct clk *bus_clk; > @@ -323,10 +320,9 @@ static struct pci_ops rcar_pcie_ops = { > .write = rcar_pcie_write_conf, > }; > > -static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) > +static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie, > + struct resource *res) > { > - struct resource *res = &pcie->res[win]; > - > /* Setup PCIe address space mappings for each resource */ > resource_size_t size; > resource_size_t res_start; > @@ -359,31 +355,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) > rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); > } > > -static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie) > +static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci) > { > - struct resource *res; > - int i; > - > - pcie->root_bus_nr = pcie->busn.start; > + struct resource_entry *win; > + int i = 0; > > /* Setup PCI resources */ > - for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) { > + resource_list_for_each_entry(win, &pci->resources) { > + struct resource *res = win->res; > > - res = &pcie->res[i]; > if (!res->flags) > continue; > > - rcar_pcie_setup_window(i, pcie); > - > - if (res->flags & IORESOURCE_IO) { > - phys_addr_t io_start = pci_pio_to_address(res->start); > - pci_ioremap_io(global_io_offset, io_start); > - global_io_offset += SZ_64K; > + switch (resource_type(res)) { > + case IORESOURCE_IO: > + case IORESOURCE_MEM: > + rcar_pcie_setup_window(i, pci, res); > + i++; > + break; > + case IORESOURCE_BUS: > + pci->root_bus_nr = res->start; > + break; > + default: > + continue; > } > > pci_add_resource(resource, res); > } > - pci_add_resource(resource, &pcie->busn); > > return 1; > } > @@ -923,14 +921,63 @@ static const struct of_device_id rcar_pcie_of_match[] = { > }; > MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); > > +static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci) > +{ > + pci_free_resource_list(&pci->resources); > +} > + > +static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) > +{ > + int err; > + struct device *dev = pci->dev; > + struct device_node *np = dev->of_node; > + resource_size_t iobase; > + struct resource_entry *win; > + > + err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); > + if (err) > + return err; > + > + resource_list_for_each_entry(win, &pci->resources) { > + struct resource *parent, *res = win->res; > + > + switch (resource_type(res)) { > + case IORESOURCE_IO: > + parent = &ioport_resource; > + err = pci_remap_iospace(res, iobase); > + if (err) { > + dev_warn(dev, "error %d: failed to map resource %pR\n", > + err, res); > + continue; > + } > + break; > + case IORESOURCE_MEM: > + parent = &iomem_resource; > + break; > + > + case IORESOURCE_BUS: > + default: > + continue; > + } > + > + err = devm_request_resource(dev, parent, res); > + if (err) > + goto out_release_res; > + } > + > + return 0; > + > +out_release_res: > + rcar_pcie_release_of_pci_ranges(pci); > + return err; > +} > + > static int rcar_pcie_probe(struct platform_device *pdev) > { > struct rcar_pcie *pcie; > unsigned int data; > - struct of_pci_range range; > - struct of_pci_range_parser parser; > const struct of_device_id *of_id; > - int err, win = 0; > + int err; > int (*hw_init_fn)(struct rcar_pcie *); > > pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); > @@ -940,16 +987,9 @@ static int rcar_pcie_probe(struct platform_device *pdev) > pcie->dev = &pdev->dev; > platform_set_drvdata(pdev, pcie); > > - /* Get the bus range */ > - if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) { > - dev_err(&pdev->dev, "failed to parse bus-range property\n"); > - return -EINVAL; > - } > + INIT_LIST_HEAD(&pcie->resources); > > - if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) { > - dev_err(&pdev->dev, "missing ranges property\n"); > - return -EINVAL; > - } > + rcar_pcie_parse_request_of_pci_ranges(pcie); > > err = rcar_pcie_get_resources(pdev, pcie); > if (err < 0) { > @@ -957,16 +997,6 @@ static int rcar_pcie_probe(struct platform_device *pdev) > return err; > } > > - for_each_of_pci_range(&parser, &range) { > - err = of_pci_range_to_resource(&range, pdev->dev.of_node, > - &pcie->res[win++]); > - if (err < 0) > - return err; > - > - if (win > RCAR_PCI_MAX_RESOURCES) > - break; > - } > - > err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); > if (err) > return err; > -- > 1.9.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 6a3a612..c977fa6 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -108,8 +108,6 @@ #define RCAR_PCI_MAX_RESOURCES 4 #define MAX_NR_INBOUND_MAPS 6 -static unsigned long global_io_offset; - struct rcar_msi { DECLARE_BITMAP(used, INT_PCI_MSI_NR); struct irq_domain *domain; @@ -138,8 +136,7 @@ struct rcar_pcie { #endif struct device *dev; void __iomem *base; - struct resource res[RCAR_PCI_MAX_RESOURCES]; - struct resource busn; + struct list_head resources; int root_bus_nr; struct clk *clk; struct clk *bus_clk; @@ -323,10 +320,9 @@ static struct pci_ops rcar_pcie_ops = { .write = rcar_pcie_write_conf, }; -static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) +static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie, + struct resource *res) { - struct resource *res = &pcie->res[win]; - /* Setup PCIe address space mappings for each resource */ resource_size_t size; resource_size_t res_start; @@ -359,31 +355,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); } -static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie) +static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci) { - struct resource *res; - int i; - - pcie->root_bus_nr = pcie->busn.start; + struct resource_entry *win; + int i = 0; /* Setup PCI resources */ - for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) { + resource_list_for_each_entry(win, &pci->resources) { + struct resource *res = win->res; - res = &pcie->res[i]; if (!res->flags) continue; - rcar_pcie_setup_window(i, pcie); - - if (res->flags & IORESOURCE_IO) { - phys_addr_t io_start = pci_pio_to_address(res->start); - pci_ioremap_io(global_io_offset, io_start); - global_io_offset += SZ_64K; + switch (resource_type(res)) { + case IORESOURCE_IO: + case IORESOURCE_MEM: + rcar_pcie_setup_window(i, pci, res); + i++; + break; + case IORESOURCE_BUS: + pci->root_bus_nr = res->start; + break; + default: + continue; } pci_add_resource(resource, res); } - pci_add_resource(resource, &pcie->busn); return 1; } @@ -923,14 +921,63 @@ static const struct of_device_id rcar_pcie_of_match[] = { }; MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); +static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci) +{ + pci_free_resource_list(&pci->resources); +} + +static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) +{ + int err; + struct device *dev = pci->dev; + struct device_node *np = dev->of_node; + resource_size_t iobase; + struct resource_entry *win; + + err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); + if (err) + return err; + + resource_list_for_each_entry(win, &pci->resources) { + struct resource *parent, *res = win->res; + + switch (resource_type(res)) { + case IORESOURCE_IO: + parent = &ioport_resource; + err = pci_remap_iospace(res, iobase); + if (err) { + dev_warn(dev, "error %d: failed to map resource %pR\n", + err, res); + continue; + } + break; + case IORESOURCE_MEM: + parent = &iomem_resource; + break; + + case IORESOURCE_BUS: + default: + continue; + } + + err = devm_request_resource(dev, parent, res); + if (err) + goto out_release_res; + } + + return 0; + +out_release_res: + rcar_pcie_release_of_pci_ranges(pci); + return err; +} + static int rcar_pcie_probe(struct platform_device *pdev) { struct rcar_pcie *pcie; unsigned int data; - struct of_pci_range range; - struct of_pci_range_parser parser; const struct of_device_id *of_id; - int err, win = 0; + int err; int (*hw_init_fn)(struct rcar_pcie *); pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); @@ -940,16 +987,9 @@ static int rcar_pcie_probe(struct platform_device *pdev) pcie->dev = &pdev->dev; platform_set_drvdata(pdev, pcie); - /* Get the bus range */ - if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) { - dev_err(&pdev->dev, "failed to parse bus-range property\n"); - return -EINVAL; - } + INIT_LIST_HEAD(&pcie->resources); - if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) { - dev_err(&pdev->dev, "missing ranges property\n"); - return -EINVAL; - } + rcar_pcie_parse_request_of_pci_ranges(pcie); err = rcar_pcie_get_resources(pdev, pcie); if (err < 0) { @@ -957,16 +997,6 @@ static int rcar_pcie_probe(struct platform_device *pdev) return err; } - for_each_of_pci_range(&parser, &range) { - err = of_pci_range_to_resource(&range, pdev->dev.of_node, - &pcie->res[win++]); - if (err < 0) - return err; - - if (win > RCAR_PCI_MAX_RESOURCES) - break; - } - err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); if (err) return err;
The main purpose of this change is to avoid calling pci_ioremap_io() as this is not available on arm64. However, instead of doing the range passing in this driver we can utilise of_pci_get_host_bridge_resources(). This is similar to changes made to the generic PCI host driver in commit dbf9826d "PCI: generic: Convert to DT resource parsing API". Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> --- v2: - Remove incorrect res_valid check --- drivers/pci/host/pcie-rcar.c | 116 +++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 43 deletions(-)