Message ID | 20121212163749.GA17371@arm.com |
---|---|
State | Not Applicable |
Headers | show |
On Wed, Dec 12, 2012 at 04:37:50PM +0000, Andrew Murray wrote: > DT bindings for PCI host bridges often use the ranges property to describe > memory and IO ranges - this binding tends to be the same across architectures > yet several parsing implementations exist, e.g. arch/mips/pci/pci.c, > arch/powerpc/kernel/pci-common.c, arch/sparc/kernel/pci.c and > arch/microblaze/pci/pci-common.c (clone of PPC). Some of these duplicate > functionality provided by drivers/of/address.c. > > This patch provides a common iterator-based parser for the ranges property, it > is hoped this will reduce DT representation differences between architectures > and that architectures will migrate in part to this new parser. > > It is also hoped (and the motativation for the patch) that this patch will > reduce duplication of code when writing host bridge drivers that are supported > by multiple architectures. > > This patch provides struct resources from a device tree node, e.g.: > > u32 *last = NULL; > struct resource res; > while ((last = of_pci_process_ranges(np, res, last))) { > //do something with res > } > > Platforms with quirks can then do what they like with the resource or migrate > common quirk handling to the parser. In an ideal world drivers can just request > the obtained resources and pass them on (e.g. pci_add_resource_offset). > > Signed-off-by: Andrew Murray <Andrew.Murray@arm.com> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> > --- > drivers/of/address.c | 53 +++++++++++++++++++++++++++++++++++++++++++- > include/linux/of_address.h | 7 +++++ > 2 files changed, 59 insertions(+), 1 deletions(-) Hi Andrew, I don't like iterator interfaces too much, but I can live with that. Other than that the patch looks good to me and I'll try to work it into my Tegra PCIe patch series. Just two minor comments below. > diff --git a/drivers/of/address.c b/drivers/of/address.c [...] > @@ -421,7 +472,7 @@ u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, > goto bail; > bus = of_match_bus(parent); > > - /* Cound address cells & copy address locally */ > + /* Count address cells & copy address locally */ > bus->count_cells(dev, &na, &ns); > if (!OF_CHECK_COUNTS(na, ns)) { > printk(KERN_ERR "prom_parse: Bad cell count for %s\n", This is really minor, but it should still go into a separate patch. > diff --git a/include/linux/of_address.h b/include/linux/of_address.h > index 01b925a..4582b20 100644 > --- a/include/linux/of_address.h > +++ b/include/linux/of_address.h > @@ -26,6 +26,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } > #define pci_address_to_pio pci_address_to_pio > #endif > > +const __be32 *of_pci_process_ranges(struct device_node *node, > + struct resource *res, const __be32 *from); > #else /* CONFIG_OF_ADDRESS */ > static inline int of_address_to_resource(struct device_node *dev, int index, > struct resource *r) > @@ -48,6 +50,11 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, > { > return NULL; > } > +const __be32 *of_pci_process_ranges(struct device_node *node, There should be a blank line to separate the above two lines. Thierry
On Thu, Dec 13, 2012 at 09:13:33AM +0000, Thierry Reding wrote: > Hi Andrew, > > I don't like iterator interfaces too much, but I can live with that. > Other than that the patch looks good to me and I'll try to work it into > my Tegra PCIe patch series. > > Just two minor comments below. > > > diff --git a/drivers/of/address.c b/drivers/of/address.c > [...] > > @@ -421,7 +472,7 @@ u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, > > goto bail; > > bus = of_match_bus(parent); > > > > - /* Cound address cells & copy address locally */ > > + /* Count address cells & copy address locally */ > > bus->count_cells(dev, &na, &ns); > > if (!OF_CHECK_COUNTS(na, ns)) { > > printk(KERN_ERR "prom_parse: Bad cell count for %s\n", > > This is really minor, but it should still go into a separate patch. > > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h > > index 01b925a..4582b20 100644 > > --- a/include/linux/of_address.h > > +++ b/include/linux/of_address.h > > @@ -26,6 +26,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } > > #define pci_address_to_pio pci_address_to_pio > > #endif > > > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > + struct resource *res, const __be32 *from); > > #else /* CONFIG_OF_ADDRESS */ > > static inline int of_address_to_resource(struct device_node *dev, int index, > > struct resource *r) > > @@ -48,6 +50,11 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, > > { > > return NULL; > > } > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > There should be a blank line to separate the above two lines. > Thanks for the feedback. I will send another patch for the typo and leave this patch with you for working into your existing series. Andrew Murray -- 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
On Thu, Dec 13, 2012 at 09:45:43AM +0000, Andrew Murray wrote: > On Thu, Dec 13, 2012 at 09:13:33AM +0000, Thierry Reding wrote: > > Hi Andrew, > > > > I don't like iterator interfaces too much, but I can live with that. > > Other than that the patch looks good to me and I'll try to work it into > > my Tegra PCIe patch series. > > > > Just two minor comments below. > > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c > > [...] > > > @@ -421,7 +472,7 @@ u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, > > > goto bail; > > > bus = of_match_bus(parent); > > > > > > - /* Cound address cells & copy address locally */ > > > + /* Count address cells & copy address locally */ > > > bus->count_cells(dev, &na, &ns); > > > if (!OF_CHECK_COUNTS(na, ns)) { > > > printk(KERN_ERR "prom_parse: Bad cell count for %s\n", > > > > This is really minor, but it should still go into a separate patch. > > > > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h > > > index 01b925a..4582b20 100644 > > > --- a/include/linux/of_address.h > > > +++ b/include/linux/of_address.h > > > @@ -26,6 +26,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } > > > #define pci_address_to_pio pci_address_to_pio > > > #endif > > > > > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > > + struct resource *res, const __be32 *from); > > > #else /* CONFIG_OF_ADDRESS */ > > > static inline int of_address_to_resource(struct device_node *dev, int index, > > > struct resource *r) > > > @@ -48,6 +50,11 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, > > > { > > > return NULL; > > > } > > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > > > There should be a blank line to separate the above two lines. > > > > Thanks for the feedback. > > I will send another patch for the typo and leave this patch with you for > working into your existing series. I suppose you have your own series that uses this patch? Thierry
On Thu, Dec 13, 2012 at 10:03:18AM +0000, Thierry Reding wrote: > On Thu, Dec 13, 2012 at 09:45:43AM +0000, Andrew Murray wrote: > > On Thu, Dec 13, 2012 at 09:13:33AM +0000, Thierry Reding wrote: > > > Hi Andrew, > > > > > > I don't like iterator interfaces too much, but I can live with that. > > > Other than that the patch looks good to me and I'll try to work it into > > > my Tegra PCIe patch series. > > > > > > Just two minor comments below. > > > > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c > > > [...] > > > > @@ -421,7 +472,7 @@ u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, > > > > goto bail; > > > > bus = of_match_bus(parent); > > > > > > > > - /* Cound address cells & copy address locally */ > > > > + /* Count address cells & copy address locally */ > > > > bus->count_cells(dev, &na, &ns); > > > > if (!OF_CHECK_COUNTS(na, ns)) { > > > > printk(KERN_ERR "prom_parse: Bad cell count for %s\n", > > > > > > This is really minor, but it should still go into a separate patch. > > > > > > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h > > > > index 01b925a..4582b20 100644 > > > > --- a/include/linux/of_address.h > > > > +++ b/include/linux/of_address.h > > > > @@ -26,6 +26,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } > > > > #define pci_address_to_pio pci_address_to_pio > > > > #endif > > > > > > > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > > > + struct resource *res, const __be32 *from); > > > > #else /* CONFIG_OF_ADDRESS */ > > > > static inline int of_address_to_resource(struct device_node *dev, int index, > > > > struct resource *r) > > > > @@ -48,6 +50,11 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, > > > > { > > > > return NULL; > > > > } > > > > +const __be32 *of_pci_process_ranges(struct device_node *node, > > > > > > There should be a blank line to separate the above two lines. > > > > > > > Thanks for the feedback. > > > > I will send another patch for the typo and leave this patch with you for > > working into your existing series. > > I suppose you have your own series that uses this patch? Not yet, it may be some time before I submit my PCI host bridge driver. Though I am making changes else where (e.g. this patch) which I'm hoping to submit as early as possible. I can rebase my work for these upstream dependencies. I can re-spin this patch with your suggested changes if you prefer? Andrew Murray -- 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
On Wed, Dec 12, 2012 at 4:37 PM, Andrew Murray <Andrew.Murray@arm.com> wrote: > DT bindings for PCI host bridges often use the ranges property to describe > memory and IO ranges - this binding tends to be the same across architectures > yet several parsing implementations exist, e.g. arch/mips/pci/pci.c, > arch/powerpc/kernel/pci-common.c, arch/sparc/kernel/pci.c and > arch/microblaze/pci/pci-common.c (clone of PPC). Some of these duplicate > functionality provided by drivers/of/address.c. Hi Andrew, Thanks for looking into this. This definitely needs to be done. However, I cannot merge this patch as-is because it actually makes things worse by adding yet another implementation of the parsing code. Plus it doesn't actually have any users. :-) Instead, move the existing code that you need out of arch/powerpc/kernel/pci-common.c into a shared place and add in the features you need. Bonus points if you fixup microblaze or others at the same time. g. -- 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
On Wed, Dec 12, 2012 at 04:37:50PM +0000, Andrew Murray wrote: [...] > diff --git a/drivers/of/address.c b/drivers/of/address.c [...] > + start = of_get_property(node, "ranges", &rlen); > + if (start == NULL) > + return NULL; > + > + end = start + rlen; I'm currently rewriting large parts of the Tegra PCIe controller driver and I'm trying to use this new API. This seems to work fine, except that I think this line needs to be: end = start + rlen / sizeof(__be32); Otherwise we'll try to process 4 times as many ranges as there are. Thierry
On Thu, Dec 20, 2012 at 08:25:00AM +0000, Thierry Reding wrote: > On Wed, Dec 12, 2012 at 04:37:50PM +0000, Andrew Murray wrote: > [...] > > diff --git a/drivers/of/address.c b/drivers/of/address.c > [...] > > + start = of_get_property(node, "ranges", &rlen); > > + if (start == NULL) > > + return NULL; > > + > > + end = start + rlen; > > I'm currently rewriting large parts of the Tegra PCIe controller driver > and I'm trying to use this new API. This seems to work fine, except that > I think this line needs to be: > > end = start + rlen / sizeof(__be32); > > Otherwise we'll try to process 4 times as many ranges as there are. > > Thierry Good catch. Thanks for taking this on. Andrew Murray -- 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
On Sat, Dec 15, 2012 at 01:06:41AM +0000, Grant Likely wrote: > On Wed, Dec 12, 2012 at 4:37 PM, Andrew Murray <Andrew.Murray@arm.com> wrote: > > DT bindings for PCI host bridges often use the ranges property to describe > > memory and IO ranges - this binding tends to be the same across architectures > > yet several parsing implementations exist, e.g. arch/mips/pci/pci.c, > > arch/powerpc/kernel/pci-common.c, arch/sparc/kernel/pci.c and > > arch/microblaze/pci/pci-common.c (clone of PPC). Some of these duplicate > > functionality provided by drivers/of/address.c. > > Hi Andrew, > > Thanks for looking into this. This definitely needs to be done. > > However, I cannot merge this patch as-is because it actually makes > things worse by adding yet another implementation of the parsing code. > Plus it doesn't actually have any users. :-) I understand. Though I see Thierry has included this in his patch set - I guess that means there is potentially one user now :). > > Instead, move the existing code that you need out of > arch/powerpc/kernel/pci-common.c into a shared place and add in the > features you need. Bonus points if you fixup microblaze or others at > the same time. In most part the patch I submitted was the common code from powerpc but without quirks and tie-ins to powerpc structures. I'd like to convert powerpc to using my patch and others but won't get time to do this at present :( > > g. > Andrew Murray -- 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/of/address.c b/drivers/of/address.c index 7e262a6..03bfe61 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -219,6 +219,57 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, return __of_address_to_resource(dev, addrp, size, flags, NULL, r); } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, const __be32 *from) +{ + const __be32 *start, *end; + int na, ns, np, pna; + int rlen; + struct of_bus *bus; + WARN_ON(!res); + + bus = of_match_bus(node); + bus->count_cells(node, &na, &ns); + if (!OF_CHECK_COUNTS(na, ns)) { + pr_err("Bad cell count for %s\n", node->full_name); + return NULL; + } + + pna = of_n_addr_cells(node); + np = pna + na + ns; + + start = of_get_property(node, "ranges", &rlen); + if (start == NULL) + return NULL; + + end = start + rlen; + + if (!from) + from = start; + + while (from + np <= end) { + u64 cpu_addr, size; + + cpu_addr = of_translate_address(node, from + na); + size = of_read_number(from + na + pna, ns); + res->flags = bus->get_flags(from); + from += np; + + if (cpu_addr == OF_BAD_ADDR || size == 0) + continue; + + res->name = node->full_name; + res->start = cpu_addr; + res->end = res->start + size - 1; + res->parent = res->child = res->sibling = NULL; + return from; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(of_pci_process_ranges); + #endif /* CONFIG_PCI */ /* @@ -421,7 +472,7 @@ u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, goto bail; bus = of_match_bus(parent); - /* Cound address cells & copy address locally */ + /* Count address cells & copy address locally */ bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 01b925a..4582b20 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -26,6 +26,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #define pci_address_to_pio pci_address_to_pio #endif +const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, const __be32 *from); #else /* CONFIG_OF_ADDRESS */ static inline int of_address_to_resource(struct device_node *dev, int index, struct resource *r) @@ -48,6 +50,11 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, { return NULL; } +const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, const __be32 *from) +{ + return NULL; +} #endif /* CONFIG_OF_ADDRESS */