diff mbox

Store PCIe controllers address in struct of_pci_range

Message ID 1436518099-98633-1-git-send-email-gabriele.paoloni@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Gabriele Paoloni July 10, 2015, 8:48 a.m. UTC
From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch is needed port PCIe designware to new DT parsing API
As discussed in
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317743.html
in designware we have a problem as the PCI addresses in the PCIe controller
address space are required in order to perform correct HW operation.

In order to solve this problem commit
f4c55c5a3f7f68c06cc559ed7af8b2d017cbb0a7 "PCI: designware:
Program ATU with untranslated address" added code to read the PCIe
controller start address directly from the DT ranges.

In the new DT parsing API of_pci_get_host_bridge_resources() hides the
DT parser from the host controller drivers, so it is not possible
for drivers to parse values directly from the DT.

In http://www.spinics.net/lists/linux-pci/msg42540.html we already tried
to use the new DT parsing API but there is a bug (obviously) in setting
the <*>_mod_base addresses
Applying this patch we can easily set "<*>_mod_base = win->__res.start"

This patch adds a new field in "struct of_pci_range" to store the
pci controller start address; it fills the field in of_pci_range_parser_one();
in of_pci_get_host_bridge_resources() it retrieve the resource entry
after it is created and added to the resource list and uses
entry->__res.start to store the pci controller address

the patch is based on 4.2-rc1

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 drivers/of/address.c               | 1 +
 drivers/of/of_pci.c                | 4 ++++
 drivers/pci/host/pcie-designware.c | 9 +++------
 include/linux/of_address.h         | 1 +
 4 files changed, 9 insertions(+), 6 deletions(-)

Comments

Rob Herring July 10, 2015, 7:56 p.m. UTC | #1
On Fri, Jul 10, 2015 at 3:48 AM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:
> From: gabriele paoloni <gabriele.paoloni@huawei.com>
>
> This patch is needed port PCIe designware to new DT parsing API
> As discussed in
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317743.html
> in designware we have a problem as the PCI addresses in the PCIe controller
> address space are required in order to perform correct HW operation.
>
> In order to solve this problem commit
> f4c55c5a3f7f68c06cc559ed7af8b2d017cbb0a7 "PCI: designware:

Please abbreviate hashs to 12 characters.

> Program ATU with untranslated address" added code to read the PCIe
> controller start address directly from the DT ranges.
>
> In the new DT parsing API of_pci_get_host_bridge_resources() hides the
> DT parser from the host controller drivers, so it is not possible
> for drivers to parse values directly from the DT.
>
> In http://www.spinics.net/lists/linux-pci/msg42540.html we already tried
> to use the new DT parsing API but there is a bug (obviously) in setting
> the <*>_mod_base addresses
> Applying this patch we can easily set "<*>_mod_base = win->__res.start"
>
> This patch adds a new field in "struct of_pci_range" to store the
> pci controller start address; it fills the field in of_pci_range_parser_one();
> in of_pci_get_host_bridge_resources() it retrieve the resource entry
> after it is created and added to the resource list and uses
> entry->__res.start to store the pci controller address
>
> the patch is based on 4.2-rc1
>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  drivers/of/address.c               | 1 +
>  drivers/of/of_pci.c                | 4 ++++
>  drivers/pci/host/pcie-designware.c | 9 +++------
>  include/linux/of_address.h         | 1 +
>  4 files changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 8bfda6a..52f9321 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -265,6 +265,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
>         range->pci_addr = of_read_number(parser->range + 1, ns);
>         range->cpu_addr = of_translate_address(parser->node,
>                                 parser->range + na);
> +       range->pci_ctrl_addr = of_read_number(parser->range + na, ns);

This is wrong as the correct size to read is not "ns", but the parent
bus #size-cells value.

I think "bus_addr" would be a better name. It is not the PCI
controller's address (i.e. what is in reg prop). No "pci" because it
has nothing to do with PCI bus addresses.

In general, this seems fragile as the dt address ranges/translation
may not align with the h/w ranges. For example, what if you have 2
levels of translations and you happen to need it translated with just
1 level of translation. That said, I don't really have a better
suggestion and I guess we can deal with that case if needed later.

>         range->size = of_read_number(parser->range + parser->pna + na, ns);
>
>         parser->range += parser->np;
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index 5751dc5..2ccc749 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -198,6 +198,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>
>         pr_debug("Parsing ranges property...\n");
>         for_each_of_pci_range(&parser, &range) {
> +               struct resource_entry *entry;
>                 /* Read next ranges element */
>                 if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
>                         snprintf(range_type, 4, " IO");
> @@ -240,6 +241,9 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>                 }
>
>                 pci_add_resource_offset(resources, res, res->start - range.pci_addr);
> +               entry = list_last_entry(resources, struct resource_entry, node);
> +               /*we are using __res for storing the PCI controller address*/
> +               entry->__res.start = range.pci_ctrl_addr;

You will use this in a follow-up patch? I'd like to see this just
split into core changes and DW changes. This looks like you are making
intermediate DW changes which will be removed in subsequent patches.

Rob
Gabriele Paoloni July 13, 2015, 11:07 a.m. UTC | #2
Hi Rob

Many Thanks for your review

> -----Original Message-----
> From: Rob Herring [mailto:robherring2@gmail.com]
> Sent: Friday, July 10, 2015 8:56 PM
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; Lorenzo Pieralisi; Wangzhou (B); Bjorn Helgaas; Rob
> Herring; james.morse@arm.com; Liviu Dudau; linux-pci@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
> Subject: Re: [PATCH] Store PCIe controllers address in struct
> of_pci_range
> 
> On Fri, Jul 10, 2015 at 3:48 AM, Gabriele Paoloni
> <gabriele.paoloni@huawei.com> wrote:
> > From: gabriele paoloni <gabriele.paoloni@huawei.com>
> >
> > This patch is needed port PCIe designware to new DT parsing API
> > As discussed in
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2015-
> January/317743.html
> > in designware we have a problem as the PCI addresses in the PCIe
> controller
> > address space are required in order to perform correct HW operation.
> >
> > In order to solve this problem commit
> > f4c55c5a3f7f68c06cc559ed7af8b2d017cbb0a7 "PCI: designware:
> 
> Please abbreviate hashs to 12 characters.

Sure, will do.

> 
> > Program ATU with untranslated address" added code to read the PCIe
> > controller start address directly from the DT ranges.
> >
> > In the new DT parsing API of_pci_get_host_bridge_resources() hides
> the
> > DT parser from the host controller drivers, so it is not possible
> > for drivers to parse values directly from the DT.
> >
> > In http://www.spinics.net/lists/linux-pci/msg42540.html we already
> tried
> > to use the new DT parsing API but there is a bug (obviously) in
> setting
> > the <*>_mod_base addresses
> > Applying this patch we can easily set "<*>_mod_base = win-
> >__res.start"
> >
> > This patch adds a new field in "struct of_pci_range" to store the
> > pci controller start address; it fills the field in
> of_pci_range_parser_one();
> > in of_pci_get_host_bridge_resources() it retrieve the resource entry
> > after it is created and added to the resource list and uses
> > entry->__res.start to store the pci controller address
> >
> > the patch is based on 4.2-rc1
> >
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  drivers/of/address.c               | 1 +
> >  drivers/of/of_pci.c                | 4 ++++
> >  drivers/pci/host/pcie-designware.c | 9 +++------
> >  include/linux/of_address.h         | 1 +
> >  4 files changed, 9 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 8bfda6a..52f9321 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -265,6 +265,7 @@ struct of_pci_range
> *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> >         range->pci_addr = of_read_number(parser->range + 1, ns);
> >         range->cpu_addr = of_translate_address(parser->node,
> >                                 parser->range + na);
> > +       range->pci_ctrl_addr = of_read_number(parser->range + na, ns) ;
> 
> This is wrong as the correct size to read is not "ns", but the parent
> bus #size-cells value.

Ok I will replace "ns" with "of_n_size_cells(parser->node)" 

> 
> I think "bus_addr" would be a better name. It is not the PCI
> controller's address (i.e. what is in reg prop). No "pci" because it
> has nothing to do with PCI bus addresses.

Ok I will change the name 

> 
> In general, this seems fragile as the dt address ranges/translation
> may not align with the h/w ranges. For example, what if you have 2
> levels of translations and you happen to need it translated with just
> 1 level of translation. That said, I don't really have a better
> suggestion and I guess we can deal with that case if needed later.

Ok so, we'll leave it like this for now

> 
> >         range->size = of_read_number(parser->range + parser->pna + na,
> ns);
> >
> >         parser->range += parser->np;
> > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> > index 5751dc5..2ccc749 100644
> > --- a/drivers/of/of_pci.c
> > +++ b/drivers/of/of_pci.c
> > @@ -198,6 +198,7 @@ int of_pci_get_host_bridge_resources(struct
> device_node *dev,
> >
> >         pr_debug("Parsing ranges property...\n");
> >         for_each_of_pci_range(&parser, &range) {
> > +               struct resource_entry *entry;
> >                 /* Read next ranges element */
> >                 if ((range.flags & IORESOURCE_TYPE_BITS) ==
> IORESOURCE_IO)
> >                         snprintf(range_type, 4, " IO");
> > @@ -240,6 +241,9 @@ int of_pci_get_host_bridge_resources(struct
> device_node *dev,
> >                 }
> >
> >                 pci_add_resource_offset(resources, res, res->start -
> range.pci_addr);
> > +               entry = list_last_entry(resources, struct
> resource_entry, node);
> > +               /*we are using __res for storing the PCI controller
> address*/
> > +               entry->__res.start = range.pci_ctrl_addr;
> 
> You will use this in a follow-up patch? I'd like to see this just
> split into core changes and DW changes. This looks like you are making
> intermediate DW changes which will be removed in subsequent patches.
> 
> Rob
Gabriele Paoloni July 13, 2015, 12:59 p.m. UTC | #3
Sorry I just realized I forgot to reply to the last item

Gab

> -----Original Message-----
> From: Gabriele Paoloni
> Sent: Monday, July 13, 2015 12:07 PM
> To: 'Rob Herring'
> Cc: Arnd Bergmann; Lorenzo Pieralisi; Wangzhou (B); Bjorn Helgaas; Rob
> Herring; james.morse@arm.com; Liviu Dudau; linux-pci@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
> Subject: RE: [PATCH] Store PCIe controllers address in struct
> of_pci_range
> 
> Hi Rob
> 
> Many Thanks for your review
> 
> > -----Original Message-----
> > From: Rob Herring [mailto:robherring2@gmail.com]
> > Sent: Friday, July 10, 2015 8:56 PM
> > To: Gabriele Paoloni
> > Cc: Arnd Bergmann; Lorenzo Pieralisi; Wangzhou (B); Bjorn Helgaas;
> Rob
> > Herring; james.morse@arm.com; Liviu Dudau; linux-pci@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> > Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu (Kenneth)
> > Subject: Re: [PATCH] Store PCIe controllers address in struct
> > of_pci_range
> >
> > On Fri, Jul 10, 2015 at 3:48 AM, Gabriele Paoloni
> > <gabriele.paoloni@huawei.com> wrote:
> > > From: gabriele paoloni <gabriele.paoloni@huawei.com>
> > >
> > > This patch is needed port PCIe designware to new DT parsing API
> > > As discussed in
> > > http://lists.infradead.org/pipermail/linux-arm-kernel/2015-
> > January/317743.html
> > > in designware we have a problem as the PCI addresses in the PCIe
> > controller
> > > address space are required in order to perform correct HW operation.
> > >
> > > In order to solve this problem commit
> > > f4c55c5a3f7f68c06cc559ed7af8b2d017cbb0a7 "PCI: designware:
> >
> > Please abbreviate hashs to 12 characters.
> 
> Sure, will do.
> 
> >
> > > Program ATU with untranslated address" added code to read the PCIe
> > > controller start address directly from the DT ranges.
> > >
> > > In the new DT parsing API of_pci_get_host_bridge_resources() hides
> > the
> > > DT parser from the host controller drivers, so it is not possible
> > > for drivers to parse values directly from the DT.
> > >
> > > In http://www.spinics.net/lists/linux-pci/msg42540.html we already
> > tried
> > > to use the new DT parsing API but there is a bug (obviously) in
> > setting
> > > the <*>_mod_base addresses
> > > Applying this patch we can easily set "<*>_mod_base = win-
> > >__res.start"
> > >
> > > This patch adds a new field in "struct of_pci_range" to store the
> > > pci controller start address; it fills the field in
> > of_pci_range_parser_one();
> > > in of_pci_get_host_bridge_resources() it retrieve the resource
> entry
> > > after it is created and added to the resource list and uses
> > > entry->__res.start to store the pci controller address
> > >
> > > the patch is based on 4.2-rc1
> > >
> > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > ---
> > >  drivers/of/address.c               | 1 +
> > >  drivers/of/of_pci.c                | 4 ++++
> > >  drivers/pci/host/pcie-designware.c | 9 +++------
> > >  include/linux/of_address.h         | 1 +
> > >  4 files changed, 9 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index 8bfda6a..52f9321 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -265,6 +265,7 @@ struct of_pci_range
> > *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> > >         range->pci_addr = of_read_number(parser->range + 1, ns);
> > >         range->cpu_addr = of_translate_address(parser->node,
> > >                                 parser->range + na);
> > > +       range->pci_ctrl_addr = of_read_number(parser->range + na,
> ns) ;
> >
> > This is wrong as the correct size to read is not "ns", but the parent
> > bus #size-cells value.
> 
> Ok I will replace "ns" with "of_n_size_cells(parser->node)"
> 
> >
> > I think "bus_addr" would be a better name. It is not the PCI
> > controller's address (i.e. what is in reg prop). No "pci" because it
> > has nothing to do with PCI bus addresses.
> 
> Ok I will change the name
> 
> >
> > In general, this seems fragile as the dt address ranges/translation
> > may not align with the h/w ranges. For example, what if you have 2
> > levels of translations and you happen to need it translated with just
> > 1 level of translation. That said, I don't really have a better
> > suggestion and I guess we can deal with that case if needed later.
> 
> Ok so, we'll leave it like this for now
> 
> >
> > >         range->size = of_read_number(parser->range + parser->pna +
> na,
> > ns);
> > >
> > >         parser->range += parser->np;
> > > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> > > index 5751dc5..2ccc749 100644
> > > --- a/drivers/of/of_pci.c
> > > +++ b/drivers/of/of_pci.c
> > > @@ -198,6 +198,7 @@ int of_pci_get_host_bridge_resources(struct
> > device_node *dev,
> > >
> > >         pr_debug("Parsing ranges property...\n");
> > >         for_each_of_pci_range(&parser, &range) {
> > > +               struct resource_entry *entry;
> > >                 /* Read next ranges element */
> > >                 if ((range.flags & IORESOURCE_TYPE_BITS) ==
> > IORESOURCE_IO)
> > >                         snprintf(range_type, 4, " IO");
> > > @@ -240,6 +241,9 @@ int of_pci_get_host_bridge_resources(struct
> > device_node *dev,
> > >                 }
> > >
> > >                 pci_add_resource_offset(resources, res, res->start
> -
> > range.pci_addr);
> > > +               entry = list_last_entry(resources, struct
> > resource_entry, node);
> > > +               /*we are using __res for storing the PCI controller
> > address*/
> > > +               entry->__res.start = range.pci_ctrl_addr;
> >
> > You will use this in a follow-up patch? I'd like to see this just
> > split into core changes and DW changes. This looks like you are
> making
> > intermediate DW changes which will be removed in subsequent patches.

Ok I will split it

The changes in "drivers/pci/host/pcie-designware.c" can be removed from this patch; we can modify directly 
"[PATCH v2 2/4] PCI: designware: Add ARM64 support" in v3 patchset

> >
> > Rob
diff mbox

Patch

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 8bfda6a..52f9321 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -265,6 +265,7 @@  struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
 	range->pci_addr = of_read_number(parser->range + 1, ns);
 	range->cpu_addr = of_translate_address(parser->node,
 				parser->range + na);
+	range->pci_ctrl_addr = of_read_number(parser->range + na, ns);
 	range->size = of_read_number(parser->range + parser->pna + na, ns);
 
 	parser->range += parser->np;
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 5751dc5..2ccc749 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -198,6 +198,7 @@  int of_pci_get_host_bridge_resources(struct device_node *dev,
 
 	pr_debug("Parsing ranges property...\n");
 	for_each_of_pci_range(&parser, &range) {
+		struct resource_entry *entry;
 		/* Read next ranges element */
 		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
 			snprintf(range_type, 4, " IO");
@@ -240,6 +241,9 @@  int of_pci_get_host_bridge_resources(struct device_node *dev,
 		}
 
 		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+		entry = list_last_entry(resources, struct resource_entry, node);
+		/*we are using __res for storing the PCI controller address*/
+		entry->__res.start = range.pci_ctrl_addr;
 	}
 
 	return 0;
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 69486be..106dae6 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -416,8 +416,7 @@  int dw_pcie_host_init(struct pcie_port *pp)
 			pp->io_base = range.cpu_addr;
 
 			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
+			pp->io_mod_base = range.pci_ctrl_addr;
 		}
 		if (restype == IORESOURCE_MEM) {
 			of_pci_range_to_resource(&range, np, &pp->mem);
@@ -426,8 +425,7 @@  int dw_pcie_host_init(struct pcie_port *pp)
 			pp->mem_bus_addr = range.pci_addr;
 
 			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
+			pp->mem_mod_base = range.pci_ctrl_addr;
 		}
 		if (restype == 0) {
 			of_pci_range_to_resource(&range, np, &pp->cfg);
@@ -437,8 +435,7 @@  int dw_pcie_host_init(struct pcie_port *pp)
 			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
+			pp->cfg0_mod_base = range.pci_ctrl_addr;
 			pp->cfg1_mod_base = pp->cfg0_mod_base +
 					    pp->cfg0_size;
 		}
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index d88e81b..55bb1ae 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -16,6 +16,7 @@  struct of_pci_range {
 	u32 pci_space;
 	u64 pci_addr;
 	u64 cpu_addr;
+	u64 pci_ctrl_addr;
 	u64 size;
 	u32 flags;
 };