On Wed, Nov 17, 2010 at 11:15:44AM -0800, Stephen Neuendorffer wrote:
> unflatten_dt_node is a helper function that does most of the work to
> convert a device tree blob into tree of device nodes.  This code
> now uses a passed-in blob instead of using the single boot-time blob,
> allowing it to be called in more contexts.
> 
> Signed-off-by: Stephen Neuendorffer <[email protected]>

Bulk of the patch looks good but a bit hard to review due to the way
it is constructed (see below).

g.

> ---
>  drivers/of/fdt.c |  251 
> +++++++++++++++++++++++++++---------------------------
>  1 files changed, 127 insertions(+), 124 deletions(-)
> 
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 6ae207a..c448b2f 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -101,120 +101,7 @@ int fdt_is_compatible(unsigned long node, const char 
> *compat,
>       return 0;
>  }
>  
> -/* Everything below here references initial_boot_params directly. */
> -int __initdata dt_root_addr_cells;
> -int __initdata dt_root_size_cells;
> -
> -struct boot_param_header *initial_boot_params;
> -
> -char *find_flat_dt_string(u32 offset)
> -{
> -     return ((char *)initial_boot_params) +
> -             be32_to_cpu(initial_boot_params->off_dt_strings) + offset;
> -}
> -
> -/**
> - * of_scan_flat_dt - scan flattened tree blob and call callback on each.
> - * @it: callback function
> - * @data: context data pointer
> - *
> - * This function is used to scan the flattened device-tree, it is
> - * used to extract the memory information at boot before we can
> - * unflatten the tree
> - */
> -int __init of_scan_flat_dt(int (*it)(unsigned long node,
> -                                  const char *uname, int depth,
> -                                  void *data),
> -                        void *data)
> -{
> -     unsigned long p = ((unsigned long)initial_boot_params) +
> -             be32_to_cpu(initial_boot_params->off_dt_struct);
> -     int rc = 0;
> -     int depth = -1;
> -
> -     do {
> -             u32 tag = be32_to_cpup((__be32 *)p);
> -             char *pathp;
> -
> -             p += 4;
> -             if (tag == OF_DT_END_NODE) {
> -                     depth--;
> -                     continue;
> -             }
> -             if (tag == OF_DT_NOP)
> -                     continue;
> -             if (tag == OF_DT_END)
> -                     break;
> -             if (tag == OF_DT_PROP) {
> -                     u32 sz = be32_to_cpup((__be32 *)p);
> -                     p += 8;
> -                     if (be32_to_cpu(initial_boot_params->version) < 0x10)
> -                             p = ALIGN(p, sz >= 8 ? 8 : 4);
> -                     p += sz;
> -                     p = ALIGN(p, 4);
> -                     continue;
> -             }
> -             if (tag != OF_DT_BEGIN_NODE) {
> -                     pr_err("Invalid tag %x in flat device tree!\n", tag);
> -                     return -EINVAL;
> -             }
> -             depth++;
> -             pathp = (char *)p;
> -             p = ALIGN(p + strlen(pathp) + 1, 4);
> -             if ((*pathp) == '/') {
> -                     char *lp, *np;
> -                     for (lp = NULL, np = pathp; *np; np++)
> -                             if ((*np) == '/')
> -                                     lp = np+1;
> -                     if (lp != NULL)
> -                             pathp = lp;
> -             }
> -             rc = it(p, pathp, depth, data);
> -             if (rc != 0)
> -                     break;
> -     } while (1);
> -
> -     return rc;
> -}
> -
> -/**
> - * of_get_flat_dt_root - find the root node in the flat blob
> - */
> -unsigned long __init of_get_flat_dt_root(void)
> -{
> -     unsigned long p = ((unsigned long)initial_boot_params) +
> -             be32_to_cpu(initial_boot_params->off_dt_struct);
> -
> -     while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
> -             p += 4;
> -     BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
> -     p += 4;
> -     return ALIGN(p + strlen((char *)p) + 1, 4);
> -}
> -
> -/**
> - * of_get_flat_dt_prop - Given a node in the flat blob, return the property 
> ptr
> - *
> - * This function can be used within scan_flattened_dt callback to get
> - * access to properties
> - */
> -void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
> -                              unsigned long *size)
> -{
> -     return fdt_get_property(node, name, size, initial_boot_params);
> -}
> -
> -/**
> - * of_flat_dt_is_compatible - Return true if given node has compat in 
> compatible list
> - * @node: node to test
> - * @compat: compatible string to compare with compatible list.
> - */
> -int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
> -{
> -     return fdt_is_compatible(node, compat, initial_boot_params);
> -}
> -
> -static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long 
> size,
> +static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
>                                      unsigned long align)
>  {
>       void *res;
> @@ -232,12 +119,14 @@ static void *__init unflatten_dt_alloc(unsigned long 
> *mem, unsigned long size,
>   * @dad: Parent struct device_node
>   * @allnextpp: pointer to ->allnext from last allocated device_node
>   * @fpsize: Size of the node path up at the current depth.
> + * @blob: The parent device tree blob
>   */
> -unsigned long __init unflatten_dt_node(unsigned long mem,
> -                                     unsigned long *p,
> -                                     struct device_node *dad,
> -                                     struct device_node ***allnextpp,
> -                                     unsigned long fpsize)
> +unsigned long unflatten_dt_node(unsigned long mem,
> +                             unsigned long *p,
> +                             struct device_node *dad,
> +                             struct device_node ***allnextpp,
> +                             unsigned long fpsize,
> +                             struct boot_param_header *blob)

Ditto here, blob should be the first argument.

>  {
>       struct device_node *np;
>       struct property *pp, **prev_pp = NULL;
> @@ -333,10 +222,10 @@ unsigned long __init unflatten_dt_node(unsigned long 
> mem,
>               sz = be32_to_cpup((__be32 *)(*p));
>               noff = be32_to_cpup((__be32 *)((*p) + 4));
>               *p += 8;
> -             if (be32_to_cpu(initial_boot_params->version) < 0x10)
> +             if (be32_to_cpu(blob->version) < 0x10)
>                       *p = ALIGN(*p, sz >= 8 ? 8 : 4);
>  
> -             pname = find_flat_dt_string(noff);
> +             pname = fdt_get_string(noff, blob);
>               if (pname == NULL) {
>                       pr_info("Can't find property name in list !\n");
>                       break;
> @@ -415,7 +304,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
>               if (tag == OF_DT_NOP)
>                       *p += 4;
>               else
> -                     mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
> +                     mem = unflatten_dt_node(mem, p, np, allnextpp,
> +                                             fpsize, blob);
>               tag = be32_to_cpup((__be32 *)(*p));
>       }
>       if (tag != OF_DT_END_NODE) {
> @@ -426,6 +316,119 @@ unsigned long __init unflatten_dt_node(unsigned long 
> mem,
>       return mem;
>  }
>  
> +/* Everything below here references initial_boot_params directly. */

Unfortunately moving stuff around like this makes the patch harder to
review because mechanical movement is mixed in with functional
changes.  Can you split the rearrangement into a separate patch?


> +int __initdata dt_root_addr_cells;
> +int __initdata dt_root_size_cells;
> +
> +struct boot_param_header *initial_boot_params;
> +
> +char *find_flat_dt_string(u32 offset)
> +{
> +     return ((char *)initial_boot_params) +
> +             be32_to_cpu(initial_boot_params->off_dt_strings) + offset;
> +}

Shouldn't the body of find_flat_dt_string be using the new
fdt_get_string function from patch 1?  Or better yet, convert all
existing users to the new function?  (There are no users of
find_flat_dt_string outside of fdt.c).

> +
> +/**
> + * of_scan_flat_dt - scan flattened tree blob and call callback on each.
> + * @it: callback function
> + * @data: context data pointer
> + *
> + * This function is used to scan the flattened device-tree, it is
> + * used to extract the memory information at boot before we can
> + * unflatten the tree
> + */
> +int __init of_scan_flat_dt(int (*it)(unsigned long node,
> +                                  const char *uname, int depth,
> +                                  void *data),
> +                        void *data)
> +{
> +     unsigned long p = ((unsigned long)initial_boot_params) +
> +             be32_to_cpu(initial_boot_params->off_dt_struct);
> +     int rc = 0;
> +     int depth = -1;
> +
> +     do {
> +             u32 tag = be32_to_cpup((__be32 *)p);
> +             char *pathp;
> +
> +             p += 4;
> +             if (tag == OF_DT_END_NODE) {
> +                     depth--;
> +                     continue;
> +             }
> +             if (tag == OF_DT_NOP)
> +                     continue;
> +             if (tag == OF_DT_END)
> +                     break;
> +             if (tag == OF_DT_PROP) {
> +                     u32 sz = be32_to_cpup((__be32 *)p);
> +                     p += 8;
> +                     if (be32_to_cpu(initial_boot_params->version) < 0x10)
> +                             p = ALIGN(p, sz >= 8 ? 8 : 4);
> +                     p += sz;
> +                     p = ALIGN(p, 4);
> +                     continue;
> +             }
> +             if (tag != OF_DT_BEGIN_NODE) {
> +                     pr_err("Invalid tag %x in flat device tree!\n", tag);
> +                     return -EINVAL;
> +             }
> +             depth++;
> +             pathp = (char *)p;
> +             p = ALIGN(p + strlen(pathp) + 1, 4);
> +             if ((*pathp) == '/') {
> +                     char *lp, *np;
> +                     for (lp = NULL, np = pathp; *np; np++)
> +                             if ((*np) == '/')
> +                                     lp = np+1;
> +                     if (lp != NULL)
> +                             pathp = lp;
> +             }
> +             rc = it(p, pathp, depth, data);
> +             if (rc != 0)
> +                     break;
> +     } while (1);
> +
> +     return rc;
> +}
> +
> +/**
> + * of_get_flat_dt_root - find the root node in the flat blob
> + */
> +unsigned long __init of_get_flat_dt_root(void)
> +{
> +     unsigned long p = ((unsigned long)initial_boot_params) +
> +             be32_to_cpu(initial_boot_params->off_dt_struct);
> +
> +     while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
> +             p += 4;
> +     BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
> +     p += 4;
> +     return ALIGN(p + strlen((char *)p) + 1, 4);
> +}

There should also be a generic version of this which accepts a blob
pointer.

> +
> +/**
> + * of_get_flat_dt_prop - Given a node in the flat blob, return the property 
> ptr
> + *
> + * This function can be used within scan_flattened_dt callback to get
> + * access to properties
> + */
> +void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
> +                              unsigned long *size)
> +{
> +     return fdt_get_property(node, name, size, initial_boot_params);
> +}
> +
> +/**
> + * of_flat_dt_is_compatible - Return true if given node has compat in 
> compatible list
> + * @node: node to test
> + * @compat: compatible string to compare with compatible list.
> + */
> +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
> +{
> +     return fdt_is_compatible(node, compat, initial_boot_params);
> +}
> +
>  #ifdef CONFIG_BLK_DEV_INITRD
>  /**
>   * early_init_dt_check_for_initrd - Decode initrd location from flat tree
> @@ -607,7 +610,7 @@ void __init unflatten_device_tree(void)
>       /* First pass, scan for size */
>       start = ((unsigned long)initial_boot_params) +
>               be32_to_cpu(initial_boot_params->off_dt_struct);
> -     size = unflatten_dt_node(0, &start, NULL, NULL, 0);
> +     size = unflatten_dt_node(0, &start, NULL, NULL, 0, initial_boot_params);
>       size = (size | 3) + 1;
>  
>       pr_debug("  size is %lx, allocating...\n", size);
> @@ -624,7 +627,7 @@ void __init unflatten_device_tree(void)
>       /* Second pass, do actual unflattening */
>       start = ((unsigned long)initial_boot_params) +
>               be32_to_cpu(initial_boot_params->off_dt_struct);
> -     unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
> +     unflatten_dt_node(mem, &start, NULL, &allnextp, 0, initial_boot_params);
>       if (be32_to_cpup((__be32 *)start) != OF_DT_END)
>               pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
>       if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
> -- 
> 1.5.6.6
> 
> 
> 
> This email and any attachments are intended for the sole use of the named 
> recipient(s) and contain(s) confidential information that may be proprietary, 
> privileged or copyrighted under applicable law. If you are not the intended 
> recipient, do not read, copy, or forward this email message or any 
> attachments. Delete this email message and any attachments immediately.
> 
> 
_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to