diff options
author | Leif Lindholm <leif.lindholm@linaro.org> | 2014-11-28 06:34:28 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-12-03 18:12:36 -0500 |
commit | 75c28c09af99a0db0ccd8b4395469761aa736543 (patch) | |
tree | df35296e1dc01e57203f0d6522918e48d636fdba | |
parent | 2a9d832cc9aae21ea827520fef635b6c49a06c6d (diff) |
of: add optional options parameter to of_find_node_by_path()
Update of_find_node_by_path():
1) Rename function to of_find_node_opts_by_path(), adding an optional
pointer argument. Provide a static inline wrapper version of
of_find_node_by_path() which calls the new function with NULL as
the optional argument.
2) Ignore any part of the path beyond and including the ':' separator.
3) Set the new provided pointer argument to the beginning of the string
following the ':' separator.
4: Add tests.
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
-rw-r--r-- | drivers/of/base.c | 20 | ||||
-rw-r--r-- | drivers/of/unittest.c | 30 | ||||
-rw-r--r-- | include/linux/of.h | 14 |
3 files changed, 59 insertions, 5 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 99bc95e83d09..bdf051d0a7e6 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -714,10 +714,15 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
714 | { | 714 | { |
715 | struct device_node *child; | 715 | struct device_node *child; |
716 | int len = strchrnul(path, '/') - path; | 716 | int len = strchrnul(path, '/') - path; |
717 | int term; | ||
717 | 718 | ||
718 | if (!len) | 719 | if (!len) |
719 | return NULL; | 720 | return NULL; |
720 | 721 | ||
722 | term = strchrnul(path, ':') - path; | ||
723 | if (term < len) | ||
724 | len = term; | ||
725 | |||
721 | __for_each_child_of_node(parent, child) { | 726 | __for_each_child_of_node(parent, child) { |
722 | const char *name = strrchr(child->full_name, '/'); | 727 | const char *name = strrchr(child->full_name, '/'); |
723 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) | 728 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) |
@@ -730,11 +735,14 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
730 | } | 735 | } |
731 | 736 | ||
732 | /** | 737 | /** |
733 | * of_find_node_by_path - Find a node matching a full OF path | 738 | * of_find_node_opts_by_path - Find a node matching a full OF path |
734 | * @path: Either the full path to match, or if the path does not | 739 | * @path: Either the full path to match, or if the path does not |
735 | * start with '/', the name of a property of the /aliases | 740 | * start with '/', the name of a property of the /aliases |
736 | * node (an alias). In the case of an alias, the node | 741 | * node (an alias). In the case of an alias, the node |
737 | * matching the alias' value will be returned. | 742 | * matching the alias' value will be returned. |
743 | * @opts: Address of a pointer into which to store the start of | ||
744 | * an options string appended to the end of the path with | ||
745 | * a ':' separator. | ||
738 | * | 746 | * |
739 | * Valid paths: | 747 | * Valid paths: |
740 | * /foo/bar Full path | 748 | * /foo/bar Full path |
@@ -744,11 +752,15 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
744 | * Returns a node pointer with refcount incremented, use | 752 | * Returns a node pointer with refcount incremented, use |
745 | * of_node_put() on it when done. | 753 | * of_node_put() on it when done. |
746 | */ | 754 | */ |
747 | struct device_node *of_find_node_by_path(const char *path) | 755 | struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) |
748 | { | 756 | { |
749 | struct device_node *np = NULL; | 757 | struct device_node *np = NULL; |
750 | struct property *pp; | 758 | struct property *pp; |
751 | unsigned long flags; | 759 | unsigned long flags; |
760 | const char *separator = strchr(path, ':'); | ||
761 | |||
762 | if (opts) | ||
763 | *opts = separator ? separator + 1 : NULL; | ||
752 | 764 | ||
753 | if (strcmp(path, "/") == 0) | 765 | if (strcmp(path, "/") == 0) |
754 | return of_node_get(of_root); | 766 | return of_node_get(of_root); |
@@ -756,7 +768,7 @@ struct device_node *of_find_node_by_path(const char *path) | |||
756 | /* The path could begin with an alias */ | 768 | /* The path could begin with an alias */ |
757 | if (*path != '/') { | 769 | if (*path != '/') { |
758 | char *p = strchrnul(path, '/'); | 770 | char *p = strchrnul(path, '/'); |
759 | int len = p - path; | 771 | int len = separator ? separator - path : p - path; |
760 | 772 | ||
761 | /* of_aliases must not be NULL */ | 773 | /* of_aliases must not be NULL */ |
762 | if (!of_aliases) | 774 | if (!of_aliases) |
@@ -785,7 +797,7 @@ struct device_node *of_find_node_by_path(const char *path) | |||
785 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 797 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
786 | return np; | 798 | return np; |
787 | } | 799 | } |
788 | EXPORT_SYMBOL(of_find_node_by_path); | 800 | EXPORT_SYMBOL(of_find_node_opts_by_path); |
789 | 801 | ||
790 | /** | 802 | /** |
791 | * of_find_node_by_name - Find a node by its "name" property | 803 | * of_find_node_by_name - Find a node by its "name" property |
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 7a7ae07d592f..1807a0458648 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c | |||
@@ -47,6 +47,7 @@ static bool selftest_live_tree; | |||
47 | static void __init of_selftest_find_node_by_name(void) | 47 | static void __init of_selftest_find_node_by_name(void) |
48 | { | 48 | { |
49 | struct device_node *np; | 49 | struct device_node *np; |
50 | const char *options; | ||
50 | 51 | ||
51 | np = of_find_node_by_path("/testcase-data"); | 52 | np = of_find_node_by_path("/testcase-data"); |
52 | selftest(np && !strcmp("/testcase-data", np->full_name), | 53 | selftest(np && !strcmp("/testcase-data", np->full_name), |
@@ -87,6 +88,35 @@ static void __init of_selftest_find_node_by_name(void) | |||
87 | np = of_find_node_by_path("testcase-alias/missing-path"); | 88 | np = of_find_node_by_path("testcase-alias/missing-path"); |
88 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); | 89 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); |
89 | of_node_put(np); | 90 | of_node_put(np); |
91 | |||
92 | np = of_find_node_opts_by_path("/testcase-data:testoption", &options); | ||
93 | selftest(np && !strcmp("testoption", options), | ||
94 | "option path test failed\n"); | ||
95 | of_node_put(np); | ||
96 | |||
97 | np = of_find_node_opts_by_path("/testcase-data:testoption", NULL); | ||
98 | selftest(np, "NULL option path test failed\n"); | ||
99 | of_node_put(np); | ||
100 | |||
101 | np = of_find_node_opts_by_path("testcase-alias:testaliasoption", | ||
102 | &options); | ||
103 | selftest(np && !strcmp("testaliasoption", options), | ||
104 | "option alias path test failed\n"); | ||
105 | of_node_put(np); | ||
106 | |||
107 | np = of_find_node_opts_by_path("testcase-alias:testaliasoption", NULL); | ||
108 | selftest(np, "NULL option alias path test failed\n"); | ||
109 | of_node_put(np); | ||
110 | |||
111 | options = "testoption"; | ||
112 | np = of_find_node_opts_by_path("testcase-alias", &options); | ||
113 | selftest(np && !options, "option clearing test failed\n"); | ||
114 | of_node_put(np); | ||
115 | |||
116 | options = "testoption"; | ||
117 | np = of_find_node_opts_by_path("/", &options); | ||
118 | selftest(np && !options, "option clearing root node test failed\n"); | ||
119 | of_node_put(np); | ||
90 | } | 120 | } |
91 | 121 | ||
92 | static void __init of_selftest_dynamic(void) | 122 | static void __init of_selftest_dynamic(void) |
diff --git a/include/linux/of.h b/include/linux/of.h index aa01cf5852f8..8b021db3e16e 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -236,7 +236,13 @@ extern struct device_node *of_find_matching_node_and_match( | |||
236 | const struct of_device_id *matches, | 236 | const struct of_device_id *matches, |
237 | const struct of_device_id **match); | 237 | const struct of_device_id **match); |
238 | 238 | ||
239 | extern struct device_node *of_find_node_by_path(const char *path); | 239 | extern struct device_node *of_find_node_opts_by_path(const char *path, |
240 | const char **opts); | ||
241 | static inline struct device_node *of_find_node_by_path(const char *path) | ||
242 | { | ||
243 | return of_find_node_opts_by_path(path, NULL); | ||
244 | } | ||
245 | |||
240 | extern struct device_node *of_find_node_by_phandle(phandle handle); | 246 | extern struct device_node *of_find_node_by_phandle(phandle handle); |
241 | extern struct device_node *of_get_parent(const struct device_node *node); | 247 | extern struct device_node *of_get_parent(const struct device_node *node); |
242 | extern struct device_node *of_get_next_parent(struct device_node *node); | 248 | extern struct device_node *of_get_next_parent(struct device_node *node); |
@@ -383,6 +389,12 @@ static inline struct device_node *of_find_node_by_path(const char *path) | |||
383 | return NULL; | 389 | return NULL; |
384 | } | 390 | } |
385 | 391 | ||
392 | static inline struct device_node *of_find_node_opts_by_path(const char *path, | ||
393 | const char **opts) | ||
394 | { | ||
395 | return NULL; | ||
396 | } | ||
397 | |||
386 | static inline struct device_node *of_get_parent(const struct device_node *node) | 398 | static inline struct device_node *of_get_parent(const struct device_node *node) |
387 | { | 399 | { |
388 | return NULL; | 400 | return NULL; |