Add a function to find the next node that has a given property, whatever its value, walking the tree in depth-first order. This is needed by the MTD virtual concat support to find all partitions with a "part-concat-next" property.
Also export ofnode_dfs_next(), which it uses to step through the tree, and add tests for both. Signed-off-by: Padmarao Begari <[email protected]> --- Changes in v2: - New patch: move the DFS helpers from the MTD driver to ofnode and add tests checkpatch reports 'Please use a blank line after function/struct/union/enum declarations' for each DM_TEST() line. DM_TEST() is placed directly after its test function, as in the other tests. drivers/core/ofnode.c | 31 ++++++++++++++++++++++++ include/dm/ofnode.h | 23 ++++++++++++++++++ test/dm/ofnode.c | 55 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index b5d13c43db1..29d2041086a 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1791,6 +1791,37 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname, } } +ofnode ofnode_dfs_next(ofnode node) +{ + ofnode child, sibling; + + child = ofnode_first_subnode(node); + if (ofnode_valid(child)) + return child; + + while (ofnode_valid(node)) { + sibling = ofnode_next_subnode(node); + if (ofnode_valid(sibling)) + return sibling; + node = ofnode_get_parent(node); + } + + return ofnode_null(); +} + +ofnode ofnode_find_node_with_property(ofnode from, const char *propname) +{ + ofnode node; + + node = ofnode_valid(from) ? ofnode_dfs_next(from) : ofnode_root(); + for (; ofnode_valid(node); node = ofnode_dfs_next(node)) { + if (ofnode_has_property(node, propname)) + return node; + } + + return ofnode_null(); +} + int ofnode_write_prop(ofnode node, const char *propname, const void *value, int len, bool copy) { diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index c905e86b283..5cd378e9735 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1488,6 +1488,29 @@ ofnode ofnode_by_compatible(ofnode from, const char *compat); ofnode ofnode_by_prop_value(ofnode from, const char *propname, const void *propval, int proplen); +/** + * ofnode_dfs_next() - Get the next node in depth-first order + * + * Return the first subnode of @node if it has one, otherwise its next sibling, + * otherwise the next sibling of the nearest parent that has one. + * + * @node: valid node to start from + * Return: next node, or ofnode_null() at the end of the tree + */ +ofnode ofnode_dfs_next(ofnode node); + +/** + * ofnode_find_node_with_property() - Find the next node with a property + * + * Walk the tree in depth-first order, starting after @from, and return the + * first node that has a property called @propname, whatever its value. + * + * @from: ofnode to start after (use ofnode_null() to start at the root) + * @propname: name of the property to look for + * Return: ofnode found, or ofnode_null() if none + */ +ofnode ofnode_find_node_with_property(ofnode from, const char *propname); + /** * ofnode_for_each_subnode() - iterate over all subnodes of a parent * diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 0f60c2a6281..4fb9bf8ce6e 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -212,6 +212,61 @@ static int dm_test_ofnode_by_prop_value_ot(struct unit_test_state *uts) DM_TEST(dm_test_ofnode_by_prop_value_ot, UTF_SCAN_FDT | UTF_OTHER_FDT); +/* test ofnode_dfs_next() */ +static int dm_test_ofnode_dfs_next(struct unit_test_state *uts) +{ + ofnode node; + + /* down into the first subnode */ + node = ofnode_dfs_next(ofnode_path("/some-bus")); + ut_asserteq_str("c-test@5", ofnode_get_name(node)); + + /* across to the next sibling */ + node = ofnode_dfs_next(node); + ut_asserteq_str("c-test@0", ofnode_get_name(node)); + + /* back up to the parent's next sibling */ + node = ofnode_dfs_next(ofnode_path("/buttons/btn2")); + ut_asserteq_str("buttons2", ofnode_get_name(node)); + + return 0; +} +DM_TEST(dm_test_ofnode_dfs_next, UTF_SCAN_FDT); + +/* test ofnode_find_node_with_property() */ +static int dm_test_ofnode_find_node_with_property(struct unit_test_state *uts) +{ + static const char *const expect[] = { + "a-test", "b-test", "some-bus", "c-test@5", "c-test@0", + "c-test@1", + }; + ofnode node = ofnode_null(); + int i; + + /* + * Nodes are found in depth-first order, whatever the value. Other + * tests may add nodes to /some-bus in the live tree, so stop there. + */ + for (i = 0; i < ARRAY_SIZE(expect); i++) { + node = ofnode_find_node_with_property(node, "ping-expect"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str(expect[i], ofnode_get_name(node)); + } + + /* the search can start from any node and runs to the end of the tree */ + node = ofnode_find_node_with_property(ofnode_path("/d-test"), + "ping-expect"); + ut_asserteq_str("e-test", ofnode_get_name(node)); + node = ofnode_find_node_with_property(node, "ping-expect"); + ut_assert(!ofnode_valid(node)); + + node = ofnode_find_node_with_property(ofnode_null(), "no-such-prop"); + ut_assert(!ofnode_valid(node)); + + return 0; +} +DM_TEST(dm_test_ofnode_find_node_with_property, UTF_SCAN_FDT); + /* test ofnode_read_fmap_entry() */ static int dm_test_ofnode_fmap(struct unit_test_state *uts) { -- 2.34.1
