Message ID | 20170406040158.30765-1-oohall@gmail.com |
---|---|
State | Accepted |
Headers | show |
On 04/06/2017 09:31 AM, Oliver O'Halloran wrote: > Adds two helper functions that allow device nodes to be found via > their name and unit address. One will take an integer address and > format it to a hex string while the other looks up the unit based > a user supplied string. This is handy in a few places inside the > HDAT parser. > > Signed-off-by: Oliver O'Halloran <oohall@gmail.com> > --- > core/device.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ > core/test/run-device.c | 1 + > include/device.h | 5 +++++ > 3 files changed, 56 insertions(+) > > diff --git a/core/device.c b/core/device.c > index 76c2f8481b9f..f3ee63fbc423 100644 > --- a/core/device.c > +++ b/core/device.c > @@ -21,6 +21,7 @@ > #include <libfdt/libfdt_internal.h> > #include <ccan/str/str.h> > #include <ccan/endian/endian.h> > +#include <inttypes.h> > > /* Used to give unique handles. */ > u32 last_phandle = 0; > @@ -155,6 +156,55 @@ struct dt_node *dt_new(struct dt_node *parent, const char *name) > return new; > } > > +/* > + * low level variant, we export this because there are "weird" address > + * formats, such as LPC/ISA bus addresses which have a letter to identify > + * which bus space the address is inside of. > + */ > +struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name, > + const char *addr) > +{ > + struct dt_node *node; > + > + if (list_empty(&parent->children)) > + return NULL; > + > + dt_for_each_child(parent, node) { > + const char *unit = get_unitname(node); > + int len; > + > + if (!unit) > + continue; > + > + /* match the name */ > + len = (int) (unit - node->name) - 1; > + if (strncmp(node->name, name, len)) > + continue; > + > + /* match the unit */ > + if (strcmp(unit, addr) == 0) > + return node; > + } > + > + dt_for_each_child(parent, node) { > + struct dt_node *ret = __dt_find_by_name_addr(node, name, addr); You can reuse variable 'node' instead of creating one more here. Otherwise patch looks good. Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> -Vasant
diff --git a/core/device.c b/core/device.c index 76c2f8481b9f..f3ee63fbc423 100644 --- a/core/device.c +++ b/core/device.c @@ -21,6 +21,7 @@ #include <libfdt/libfdt_internal.h> #include <ccan/str/str.h> #include <ccan/endian/endian.h> +#include <inttypes.h> /* Used to give unique handles. */ u32 last_phandle = 0; @@ -155,6 +156,55 @@ struct dt_node *dt_new(struct dt_node *parent, const char *name) return new; } +/* + * low level variant, we export this because there are "weird" address + * formats, such as LPC/ISA bus addresses which have a letter to identify + * which bus space the address is inside of. + */ +struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name, + const char *addr) +{ + struct dt_node *node; + + if (list_empty(&parent->children)) + return NULL; + + dt_for_each_child(parent, node) { + const char *unit = get_unitname(node); + int len; + + if (!unit) + continue; + + /* match the name */ + len = (int) (unit - node->name) - 1; + if (strncmp(node->name, name, len)) + continue; + + /* match the unit */ + if (strcmp(unit, addr) == 0) + return node; + } + + dt_for_each_child(parent, node) { + struct dt_node *ret = __dt_find_by_name_addr(node, name, addr); + + if (ret) + return ret; + } + + return NULL; +} + +struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name, + uint64_t addr) +{ + char addr_str[16 + 1]; /* max size of a 64bit int */ + snprintf(addr_str, sizeof(addr_str), "%" PRIx64, addr); + + return __dt_find_by_name_addr(parent, name, addr_str); +} + struct dt_node *dt_new_addr(struct dt_node *parent, const char *name, uint64_t addr) { diff --git a/core/test/run-device.c b/core/test/run-device.c index e91e5a5fc5c6..5939afc70e54 100644 --- a/core/test/run-device.c +++ b/core/test/run-device.c @@ -150,6 +150,7 @@ int main(void) assert(!list_top(&addr1->properties, struct dt_property, list)); check_path(addr1, "/addrs/addr@1337"); assert(dt_find_by_name(root, "addr@1337") == addr1); + assert(dt_find_by_name_addr(root, "addr", 0x1337) == addr1); assert(dt_find_by_path(root, "/addrs/addr@1337") == addr1); addr2 = dt_new_2addr(addrs, "2addr", 0xdead, 0xbeef); diff --git a/include/device.h b/include/device.h index 1ad403f18450..5155daadc7ee 100644 --- a/include/device.h +++ b/include/device.h @@ -247,4 +247,9 @@ u64 dt_translate_address(const struct dt_node *node, unsigned int index, */ int dt_cmp_subnodes(const struct dt_node *a, const struct dt_node *b); +struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name, + const char *addr); +struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name, + uint64_t addr); + #endif /* __DEVICE_H */
Adds two helper functions that allow device nodes to be found via their name and unit address. One will take an integer address and format it to a hex string while the other looks up the unit based a user supplied string. This is handy in a few places inside the HDAT parser. Signed-off-by: Oliver O'Halloran <oohall@gmail.com> --- core/device.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ core/test/run-device.c | 1 + include/device.h | 5 +++++ 3 files changed, 56 insertions(+)