diff mbox series

[v2,03/38] common: fdt_support: Support special case of PCI address in fdt_read_prop()

Message ID 1613663886-83811-4-git-send-email-bmeng.cn@gmail.com
State Superseded
Delegated to: Priyanka Jain
Headers show
Series ppc: qemu: Convert qemu-ppce500 to driver model and enable additional driver support | expand

Commit Message

Bin Meng Feb. 18, 2021, 3:57 p.m. UTC
At present fdt_read_prop() can only handle 1 or 2 cells. It is
called by fdt_read_range() which may be used to read PCI address
from <ranges> for a PCI bus node where the number of PCI address
cell is 3. The <ranges> property is an array of:

  { <child address> <parent address> <size in child address space> }

When trying to read <child address> from a PCI bus node using
fdt_read_prop(), as the codes below:

    /* Read <child address> */
    if (child_addr) {
        r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
                          acells);
        if (r)
            return r;
    }

it will fail, because the PCI child address is made up of 3 cells
but fdt_read_prop() cannot handle it. We advance the cell offset
by 1 so that the <child address> can be correctly read.

This adds the special handling of such case.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>

---

Changes in v2:
- add more details in the commit message, and put some comments
  in the codes to explain why

 common/fdt_support.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

Comments

Simon Glass Feb. 20, 2021, 11:54 a.m. UTC | #1
Hi Bin,

On Thu, 18 Feb 2021 at 08:58, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> At present fdt_read_prop() can only handle 1 or 2 cells. It is
> called by fdt_read_range() which may be used to read PCI address
> from <ranges> for a PCI bus node where the number of PCI address
> cell is 3. The <ranges> property is an array of:
>
>   { <child address> <parent address> <size in child address space> }
>
> When trying to read <child address> from a PCI bus node using
> fdt_read_prop(), as the codes below:
>
>     /* Read <child address> */
>     if (child_addr) {
>         r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
>                           acells);
>         if (r)
>             return r;
>     }
>
> it will fail, because the PCI child address is made up of 3 cells
> but fdt_read_prop() cannot handle it. We advance the cell offset
> by 1 so that the <child address> can be correctly read.
>
> This adds the special handling of such case.
>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>
> ---
>
> Changes in v2:
> - add more details in the commit message, and put some comments
>   in the codes to explain why
>
>  common/fdt_support.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/common/fdt_support.c b/common/fdt_support.c
> index 638eca9..17c54a3 100644
> --- a/common/fdt_support.c
> +++ b/common/fdt_support.c
> @@ -1602,22 +1602,36 @@ u64 fdt_get_base_address(const void *fdt, int node)
>  }
>
>  /*
> - * Read a property of size <prop_len>. Currently only supports 1 or 2 cells.
> + * Read a property of size <prop_len>. Currently only supports 1 or 2 cells,
> + * or 3 cells specially for a PCI address.
>   */
>  static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off,
>                          uint64_t *val, int cells)
>  {
> -       const fdt32_t *prop32 = &prop[cell_off];
> -       const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off];
> +       const fdt32_t *prop32;
> +       const unaligned_fdt64_t *prop64;
>
>         if ((cell_off + cells) > prop_len)
>                 return -FDT_ERR_NOSPACE;
>
> +       prop32 = &prop[cell_off];
> +
> +       /*
> +        * Special handling for PCI address in PCI bus <ranges>
> +        *
> +        * PCI child address is made up of 3 cells. Advance the cell offset
> +        * by 1 so that the PCI child address can be correctly read.
> +        */
> +       if (cells == 3)
> +               cell_off += 1;
> +       prop64 = (const fdt64_t *)&prop[cell_off];
> +
>         switch (cells) {
>         case 1:
>                 *val = fdt32_to_cpu(*prop32);
>                 break;
>         case 2:
> +       case 3:
>                 *val = fdt64_to_cpu(*prop64);
>                 break;
>         default:
> --
> 2.7.4
>

I'm not sure whether this is needed once PPC PCI is converted to DM.
If not, then perhaps we can revert it later. If it is then it would be
nice to have a test.

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon
Bin Meng Feb. 20, 2021, 1:03 p.m. UTC | #2
Hi Simon,

On Sat, Feb 20, 2021 at 7:55 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Bin,
>
> On Thu, 18 Feb 2021 at 08:58, Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > At present fdt_read_prop() can only handle 1 or 2 cells. It is
> > called by fdt_read_range() which may be used to read PCI address
> > from <ranges> for a PCI bus node where the number of PCI address
> > cell is 3. The <ranges> property is an array of:
> >
> >   { <child address> <parent address> <size in child address space> }
> >
> > When trying to read <child address> from a PCI bus node using
> > fdt_read_prop(), as the codes below:
> >
> >     /* Read <child address> */
> >     if (child_addr) {
> >         r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
> >                           acells);
> >         if (r)
> >             return r;
> >     }
> >
> > it will fail, because the PCI child address is made up of 3 cells
> > but fdt_read_prop() cannot handle it. We advance the cell offset
> > by 1 so that the <child address> can be correctly read.
> >
> > This adds the special handling of such case.
> >
> > Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> >
> > ---
> >
> > Changes in v2:
> > - add more details in the commit message, and put some comments
> >   in the codes to explain why
> >
> >  common/fdt_support.c | 20 +++++++++++++++++---
> >  1 file changed, 17 insertions(+), 3 deletions(-)
> >
> > diff --git a/common/fdt_support.c b/common/fdt_support.c
> > index 638eca9..17c54a3 100644
> > --- a/common/fdt_support.c
> > +++ b/common/fdt_support.c
> > @@ -1602,22 +1602,36 @@ u64 fdt_get_base_address(const void *fdt, int node)
> >  }
> >
> >  /*
> > - * Read a property of size <prop_len>. Currently only supports 1 or 2 cells.
> > + * Read a property of size <prop_len>. Currently only supports 1 or 2 cells,
> > + * or 3 cells specially for a PCI address.
> >   */
> >  static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off,
> >                          uint64_t *val, int cells)
> >  {
> > -       const fdt32_t *prop32 = &prop[cell_off];
> > -       const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off];
> > +       const fdt32_t *prop32;
> > +       const unaligned_fdt64_t *prop64;
> >
> >         if ((cell_off + cells) > prop_len)
> >                 return -FDT_ERR_NOSPACE;
> >
> > +       prop32 = &prop[cell_off];
> > +
> > +       /*
> > +        * Special handling for PCI address in PCI bus <ranges>
> > +        *
> > +        * PCI child address is made up of 3 cells. Advance the cell offset
> > +        * by 1 so that the PCI child address can be correctly read.
> > +        */
> > +       if (cells == 3)
> > +               cell_off += 1;
> > +       prop64 = (const fdt64_t *)&prop[cell_off];
> > +
> >         switch (cells) {
> >         case 1:
> >                 *val = fdt32_to_cpu(*prop32);
> >                 break;
> >         case 2:
> > +       case 3:
> >                 *val = fdt64_to_cpu(*prop64);
> >                 break;
> >         default:
> > --
> > 2.7.4
> >
>
> I'm not sure whether this is needed once PPC PCI is converted to DM.
> If not, then perhaps we can revert it later. If it is then it would be

I think we can completely remove these APIs once PPC PCI is converted
to DM. We can revisit this later.

> nice to have a test.
>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Bin
Priyanka Jain Feb. 22, 2021, 7:42 a.m. UTC | #3
>-----Original Message-----
>From: Bin Meng <bmeng.cn@gmail.com>
>Sent: Thursday, February 18, 2021 9:28 PM
>To: Simon Glass <sjg@chromium.org>; Alexander Graf <agraf@csgraf.de>;
>Priyanka Jain <priyanka.jain@nxp.com>
>Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Tom Rini
><trini@konsulko.com>
>Subject: [PATCH v2 03/38] common: fdt_support: Support special case of PCI
>address in fdt_read_prop()
>
>At present fdt_read_prop() can only handle 1 or 2 cells. It is called by
>fdt_read_range() which may be used to read PCI address from <ranges> for a
>PCI bus node where the number of PCI address cell is 3. The <ranges>
>property is an array of:
>
>  { <child address> <parent address> <size in child address space> }
>
>When trying to read <child address> from a PCI bus node using
>fdt_read_prop(), as the codes below:
>
>    /* Read <child address> */
>    if (child_addr) {
>        r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
>                          acells);
>        if (r)
>            return r;
>    }
>
>it will fail, because the PCI child address is made up of 3 cells but
>fdt_read_prop() cannot handle it. We advance the cell offset by 1 so that the
><child address> can be correctly read.
>
>This adds the special handling of such case.
>
>Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
>
>---
>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
diff mbox series

Patch

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 638eca9..17c54a3 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1602,22 +1602,36 @@  u64 fdt_get_base_address(const void *fdt, int node)
 }
 
 /*
- * Read a property of size <prop_len>. Currently only supports 1 or 2 cells.
+ * Read a property of size <prop_len>. Currently only supports 1 or 2 cells,
+ * or 3 cells specially for a PCI address.
  */
 static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off,
 			 uint64_t *val, int cells)
 {
-	const fdt32_t *prop32 = &prop[cell_off];
-	const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off];
+	const fdt32_t *prop32;
+	const unaligned_fdt64_t *prop64;
 
 	if ((cell_off + cells) > prop_len)
 		return -FDT_ERR_NOSPACE;
 
+	prop32 = &prop[cell_off];
+
+	/*
+	 * Special handling for PCI address in PCI bus <ranges>
+	 *
+	 * PCI child address is made up of 3 cells. Advance the cell offset
+	 * by 1 so that the PCI child address can be correctly read.
+	 */
+	if (cells == 3)
+		cell_off += 1;
+	prop64 = (const fdt64_t *)&prop[cell_off];
+
 	switch (cells) {
 	case 1:
 		*val = fdt32_to_cpu(*prop32);
 		break;
 	case 2:
+	case 3:
 		*val = fdt64_to_cpu(*prop64);
 		break;
 	default: