diff options
author | David Vrabel <david.vrabel@citrix.com> | 2012-03-22 14:26:45 +0000 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2012-03-22 14:26:45 +0000 |
commit | 9cf4a9a467171c8a2c3d97c2bfadb1bc8b15a3d6 (patch) | |
tree | fd1c0a95ab13aaf23d06edf9253b54eb2fb7283d /xen/common/device_tree.c | |
parent | 1140ce1534c70bcc1b87d6f9caa4eebead87e5de (diff) | |
download | xen-9cf4a9a467171c8a2c3d97c2bfadb1bc8b15a3d6.tar.gz xen-9cf4a9a467171c8a2c3d97c2bfadb1bc8b15a3d6.tar.bz2 xen-9cf4a9a467171c8a2c3d97c2bfadb1bc8b15a3d6.zip |
device tree: add device_tree_for_each_node()
Add device_tree_for_each_node() to iterate over all nodes in a flat
device tree. Use this in device_tree_early_init().
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'xen/common/device_tree.c')
-rw-r--r-- | xen/common/device_tree.c | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 5329956279..8f5d8997da 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -68,7 +68,43 @@ static u32 __init prop_by_name_u32(const void *fdt, int node, return fdt32_to_cpu(*(uint32_t*)prop->data); } +#define MAX_DEPTH 16 + +/** + * device_tree_for_each_node - iterate over all device tree nodes + * @fdt: flat device tree. + * @func: function to call for each node. + * @data: data to pass to @func. + */ +int device_tree_for_each_node(const void *fdt, + device_tree_node_func func, void *data) +{ + int node; + int depth; + u32 address_cells[MAX_DEPTH]; + u32 size_cells[MAX_DEPTH]; + int ret; + + for ( node = 0, depth = 0; + node >=0 && depth >= 0; + node = fdt_next_node(fdt, node, &depth) ) + { + if ( depth >= MAX_DEPTH ) + continue; + + address_cells[depth] = prop_by_name_u32(fdt, node, "#address-cells"); + size_cells[depth] = prop_by_name_u32(fdt, node, "#size-cells"); + + ret = func(fdt, node, fdt_get_name(fdt, node, NULL), depth, + address_cells[depth-1], size_cells[depth-1], data); + if ( ret < 0 ) + return ret; + } + return 0; +} + static void __init process_memory_node(const void *fdt, int node, + const char *name, u32 address_cells, u32 size_cells) { const struct fdt_property *prop; @@ -81,15 +117,14 @@ static void __init process_memory_node(const void *fdt, int node, if ( address_cells < 1 || size_cells < 1 ) { early_printk("fdt: node `%s': invalid #address-cells or #size-cells", - fdt_get_name(fdt, node, NULL)); + name); return; } prop = fdt_get_property(fdt, node, "reg", NULL); if ( !prop ) { - early_printk("fdt: node `%s': missing `reg' property\n", - fdt_get_name(fdt, node, NULL)); + early_printk("fdt: node `%s': missing `reg' property\n", name); return; } @@ -106,30 +141,15 @@ static void __init process_memory_node(const void *fdt, int node, } } -#define MAX_DEPTH 16 - -static void __init early_scan(const void *fdt) +static int __init early_scan_node(const void *fdt, + int node, const char *name, int depth, + u32 address_cells, u32 size_cells, + void *data) { - int node; - int depth; - u32 address_cells[MAX_DEPTH]; - u32 size_cells[MAX_DEPTH]; - - for ( node = 0; depth >= 0; node = fdt_next_node(fdt, node, &depth) ) - { - if ( depth >= MAX_DEPTH ) - { - early_printk("fdt: node '%s': nested too deep\n", - fdt_get_name(fdt, node, NULL)); - continue; - } + if ( node_matches(fdt, node, "memory") ) + process_memory_node(fdt, node, name, address_cells, size_cells); - address_cells[depth] = prop_by_name_u32(fdt, node, "#address-cells"); - size_cells[depth] = prop_by_name_u32(fdt, node, "#size-cells"); - - if ( node_matches(fdt, node, "memory") ) - process_memory_node(fdt, node, address_cells[depth-1], size_cells[depth-1]); - } + return 0; } static void __init early_print_info(void) @@ -157,7 +177,7 @@ size_t __init device_tree_early_init(const void *fdt) if ( ret < 0 ) early_panic("No valid device tree\n"); - early_scan(fdt); + device_tree_for_each_node((void *)fdt, early_scan_node, NULL); early_print_info(); return fdt_totalsize(fdt); |