DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK
@ 2016-03-26  1:12 Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 1/6] eal/fdt: introduce Flattened Device Tree API Jan Viktorin
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

Hello,

while extending the DPDK by a kind of platform devices (for the 16.07), an
access to the FDT might be necessary (or at least very helpful). This patch
series for 16.07 introduces an approach to solve this topic.

The API is designed from scratch and there is only the Linux backend for it.
The Linux backend can read and traverse the /proc/device-tree structure. The
API, however, stays as independent as possible. It is possible to:

* open the FDT in a platform independent way (rte_fdt_open/close)
* define a path in the FDT in an abstract way (rte_fdt_path)
* read strings, 32 and 64 bit values, a binary content (rte_fdt_path_readX)
* walk the FDT structure from a selected point (rte_fdt_path_walk)

I've included unit tests of the API and of the Linux implemention. Some basic
API tests are introduced in the patch 3. Then a simplified device-tree file
structure is added together with more tests testing the Linux backend (4,5).
I've left those 3 patches separated for now but I think they can be aggregated
into a single patch later.

Here, I've encounter an issue. The testing FDT files (app/test/linux-fdt) need
to be copied (or linked) to the working directory of the _test_ executable. I
have no idea, how to integrate such logic into the build system.

The API provides a very limited set of access functions. I think, it's as
minimalistic as possible while enabling all necessary operations a PMD driver
would need. However, some higher level functions would be helpful, too.

The patch series is still missing some bits (eg. better error logging).

Any comments and suggestions are welcome...

Regards
Jan


Jan Viktorin (6):
  eal/fdt: introduce Flattened Device Tree API
  eal/fdt: implement FDT API for Linux
  eal/fdt: test FDT API
  eal/fdt: add testing FDT of xgene-1 got from Linux runtime
  eal/fdt: test Linux implementation on xgene-1 FDT
  eal/fdt: export for dpdk 16.07

 app/test/Makefile                                  |   1 +
 app/test/linux-fdt/xgene1/#address-cells           | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/#size-cells              | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/compatible               | Bin 0 -> 28 bytes
 app/test/linux-fdt/xgene1/model                    | Bin 0 -> 25 bytes
 .../xgene1/soc/ethernet@17020000/local-mac-address | Bin 0 -> 6 bytes
 .../linux-fdt/xgene1/soc/ethernet@17020000/reg     | Bin 0 -> 48 bytes
 app/test/test_fdt.c                                | 484 +++++++++++++++++++++
 lib/librte_eal/common/Makefile                     |   2 +-
 lib/librte_eal/common/eal_common_fdt.c             | 317 ++++++++++++++
 lib/librte_eal/common/include/rte_fdt.h            | 185 ++++++++
 lib/librte_eal/linuxapp/eal/Makefile               |   3 +
 lib/librte_eal/linuxapp/eal/eal_fdt.c              | 336 ++++++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |  20 +
 14 files changed, 1347 insertions(+), 1 deletion(-)
 create mode 100644 app/test/linux-fdt/xgene1/#address-cells
 create mode 100644 app/test/linux-fdt/xgene1/#size-cells
 create mode 100644 app/test/linux-fdt/xgene1/compatible
 create mode 100644 app/test/linux-fdt/xgene1/model
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/local-mac-address
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg
 create mode 100644 app/test/test_fdt.c
 create mode 100644 lib/librte_eal/common/eal_common_fdt.c
 create mode 100644 lib/librte_eal/common/include/rte_fdt.h
 create mode 100644 lib/librte_eal/linuxapp/eal/eal_fdt.c

-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 1/6] eal/fdt: introduce Flattened Device Tree API
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 2/6] eal/fdt: implement FDT API for Linux Jan Viktorin
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

The API provides a way to access Flat Device Tree from EAL or from drivers.
This makes possible to discover platform devices which are not discoverable
via the PCI bus.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 lib/librte_eal/common/Makefile          |   2 +-
 lib/librte_eal/common/include/rte_fdt.h | 185 ++++++++++++++++++++++++++++++++
 2 files changed, 186 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/include/rte_fdt.h

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index f5ea0ee..8bf6410 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_pci_dev_ids.h rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h
+INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_fdt.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/include/rte_fdt.h b/lib/librte_eal/common/include/rte_fdt.h
new file mode 100644
index 0000000..444991a
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_fdt.h
@@ -0,0 +1,185 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 RehiveTech. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of RehiveTech nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_FDT_H_
+#define _RTE_FDT_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+/**
+ * @file
+ *
+ * Flat Device Tree access
+ *
+ * Common API to access FDT. Multiple FDT backends can be implemented for
+ * different platforms (Linux, BSD).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Representation of an FDT.
+ */
+struct rte_fdt;
+
+/**
+ * Open the FDT specified by the given path. The path is platform dependent.
+ * For Linux, the path is usually "/proc/device-tree".
+ */
+struct rte_fdt *rte_fdt_open(const char *path);
+
+/**
+ * Release all resources used by the given FDT.
+ */
+void rte_fdt_close(struct rte_fdt *fdt);
+
+/**
+ * Representation of a path in the FDT.
+ * It is a linked-list of path components.
+ *
+ * "amba" <- "eth0" <- "name"
+ * |----- base -----|- top -|
+ */
+struct rte_fdt_path {
+	char *name;
+	struct rte_fdt_path *top;  /**< points to the front to "my top" */
+	struct rte_fdt_path *base; /**< pointes to the back to "my base" */
+};
+
+/**
+ * Returns true if the given name is a valid name to be the rte_fdt_path
+ * component. A path component must not contain '/', '\\'.
+ * It MUST NOT be neither of: '.', '..', '' (empty).
+ */
+bool rte_fdt_path_is_valid(const char *name);
+
+/**
+ * Push a new component at the top of the path. Return the new top.
+ * The base can be NULL if there is no base yet.
+ * It returns NULL on allocation failure (the base pointer remains valid).
+ */
+struct rte_fdt_path *rte_fdt_path_pushs(struct rte_fdt_path *base,
+		const char *top);
+
+/**
+ * Drop the top of the path. Returns the base. If there is no base,
+ * it returns NULL.
+ */
+struct rte_fdt_path *rte_fdt_path_pop(struct rte_fdt_path *path);
+
+/**
+ * Duplicate the given path. Useful to preserve a deep copy of a path.
+ */
+struct rte_fdt_path *rte_fdt_path_dup(const struct rte_fdt_path *path);
+
+/**
+ * Free the given path. Returns NULL.
+ */
+struct rte_fdt_path *rte_fdt_path_free(struct rte_fdt_path *path);
+
+/**
+ * Parse the given path into the rte_fdt_path representation.
+ */
+int rte_fdt_path_parse(struct rte_fdt_path **p, const char *path);
+
+/**
+ * Construct the string representation of the given base and top using the
+ * delimiter '/'. The top can be omitted by giving NULL. The returned string
+ * should be freed by the standard free().
+ */
+char *rte_fdt_path_tostr(const struct rte_fdt_path *base, const char *top);
+
+/**
+ * Read raw contents of the given path.
+ * Returns the length of the read data (excluding the appended NUL).
+ */
+ssize_t rte_fdt_path_read(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base,
+		const char *top, char *b, size_t blen);
+
+/**
+ * Read up to vmax values, each 4 bytes long. Returns the number of read
+ * values or a negative in case of an error. If zero is returned, the path
+ * does not exist.
+ */
+ssize_t rte_fdt_path_read32(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		uint32_t *v, size_t vmax);
+
+/**
+ * Read up to vmax values, each 8 bytes long. Returns the number of read
+ * values or a negative in case of an error. If zero is returned, the path
+ * does not exist.
+ */
+ssize_t rte_fdt_path_read64(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		uint64_t *v, size_t vmax);
+
+/**
+ * Read contents of the given path. The result is always NUL terminated.
+ * The buffer s is to be freed by the standard free() function.
+ * Returns the length of the read data (excluding the appended NUL).
+ */
+ssize_t rte_fdt_path_reads(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base,
+		const char *top, char **s);
+
+/**
+ * Walk the current base for all available tops. For each top, the function f
+ * is called with the base, top and the context as its arguments. Returns
+ * * 0 on success,
+ * * 1 on success with forced stop,
+ * * a positive value (defined by the given f function),
+ * * a negative value on a failure (unrelated to the f function).
+ *
+ * The function f should return:
+ *
+ * * 0 on success (to continue the walking),
+ * * 1 on success (to stop the walking),
+ * * any other (positive) value on failure (stops walking and returns
+ *   the value).
+ */
+int rte_fdt_path_walk(struct rte_fdt *fdt, const struct rte_fdt_path *base,
+		int (*f)(struct rte_fdt *, const struct rte_fdt_path *,
+			const char *, void *), void *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 2/6] eal/fdt: implement FDT API for Linux
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 1/6] eal/fdt: introduce Flattened Device Tree API Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 3/6] eal/fdt: test FDT API Jan Viktorin
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

The Linux FDT API implementation reads the /proc/device-tree structure. Each
FDT entry is represented by a file or directory there.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 lib/librte_eal/common/eal_common_fdt.c | 317 +++++++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/Makefile   |   3 +
 lib/librte_eal/linuxapp/eal/eal_fdt.c  | 336 +++++++++++++++++++++++++++++++++
 3 files changed, 656 insertions(+)
 create mode 100644 lib/librte_eal/common/eal_common_fdt.c
 create mode 100644 lib/librte_eal/linuxapp/eal/eal_fdt.c

diff --git a/lib/librte_eal/common/eal_common_fdt.c b/lib/librte_eal/common/eal_common_fdt.c
new file mode 100644
index 0000000..29d08c1
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_fdt.c
@@ -0,0 +1,317 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 RehiveTech. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of RehiveTech nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <rte_fdt.h>
+#include <rte_debug.h>
+
+bool rte_fdt_path_is_valid(const char *name)
+{
+	size_t i;
+	size_t len = 0;
+
+	if (name == NULL)
+		return 0;
+
+	len = strlen(name);
+	if (len == 0)
+		return 0;
+
+	if (!strcmp(name, "."))
+		return 0;
+	if (!strcmp(name, ".."))
+		return 0;
+
+	for (i = 0; i < len; ++i) {
+		if (strchr("/\\", name[i]))
+			return 0;
+	}
+
+	return 1;
+}
+
+struct rte_fdt_path *rte_fdt_path_pushs(struct rte_fdt_path *base,
+		const char *top)
+{
+	struct rte_fdt_path *path;
+	size_t toplen;
+
+	RTE_VERIFY(top != NULL);
+	RTE_VERIFY(rte_fdt_path_is_valid(top));
+
+	toplen = strlen(top);
+
+	path = malloc(sizeof(*path) + toplen + 1);
+	if (path == NULL)
+		return NULL;
+
+	path->name = (char *) (path + 1);
+	memcpy(path->name, top, toplen);
+	path->name[toplen] = '\0';
+
+	path->base = base;
+	if (base != NULL)
+		base->top = path;
+
+	path->top = NULL;
+	return path;
+}
+
+struct rte_fdt_path *rte_fdt_path_pop(struct rte_fdt_path *path)
+{
+	struct rte_fdt_path *base;
+	RTE_VERIFY(path != NULL);
+
+	base = path->base;
+	free(path);
+
+	if (base != NULL)
+		base->top = NULL;
+
+	return base;
+}
+
+struct rte_fdt_path *rte_fdt_path_dup(const struct rte_fdt_path *path)
+{
+	struct rte_fdt_path *copy = NULL;
+	struct rte_fdt_path *tmp = NULL;
+	const struct rte_fdt_path *cur = path;
+
+	if (cur == NULL)
+		return NULL;
+
+	while (cur->base != NULL)
+		cur = cur->base;
+
+	/* copy all but the top most path component */
+	while (cur != path) {
+		tmp = rte_fdt_path_pushs(copy, cur->name);
+		if (tmp == NULL) {
+			rte_fdt_path_free(copy);
+			return NULL;
+		}
+
+		copy = tmp;
+		cur = cur->top;
+	}
+
+	/* copy the top most path component */
+	tmp = rte_fdt_path_pushs(copy, path->name);
+	if (tmp == NULL) {
+		rte_fdt_path_free(copy);
+		return NULL;
+	}
+
+	copy = tmp;
+	return copy;
+}
+
+struct rte_fdt_path *rte_fdt_path_free(struct rte_fdt_path *path)
+{
+	while (path != NULL)
+		path = rte_fdt_path_pop(path);
+
+	return NULL;
+}
+
+int rte_fdt_path_parse(struct rte_fdt_path **p, const char *path)
+{
+	const char *cur;
+	const char *end;
+	size_t pathlen;
+	struct rte_fdt_path *base = NULL;
+	struct rte_fdt_path *tmp = NULL;
+	char name[PATH_MAX];
+
+	if (path == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pathlen = strlen(path);
+	if (pathlen == 0) {
+		errno = EINVAL;
+		return -2;
+	}
+
+	cur = path;
+
+	if (cur[0] != '/') {
+		errno = EINVAL;
+		return -3;
+	}
+
+	/* root "/" */
+	if (cur[1] == '\0') {
+		*p = NULL;
+		return 0;
+	}
+	cur += 1;
+
+	do {
+		end = strchr(cur, '/');
+		if (end == NULL)
+			end = path + pathlen;
+
+		if (end - cur == 0)
+			break; /* strip the ending '/' */
+
+		RTE_VERIFY(end >= cur);
+		RTE_VERIFY(end - cur < PATH_MAX);
+		memcpy(name, cur, end - cur);
+		name[end - cur] = '\0';
+
+		if (!strcmp(name, "."))
+			goto next_cur;
+
+		if (!strcmp(name, "..")) {
+			if (base)
+				base = rte_fdt_path_pop(base);
+			goto next_cur;
+		}
+
+		if (!rte_fdt_path_is_valid(name))
+			goto name_invalid;
+
+		tmp = rte_fdt_path_pushs(base, name);
+		if (tmp == NULL)
+			goto push_failed;
+
+		base = tmp;
+next_cur:
+		if (*end == '\0')
+			break;
+
+		cur = end + 1;
+	} while(end != '\0');
+
+	*p = base;
+	return 0;
+
+name_invalid:
+	errno = EINVAL;
+	return -4;
+push_failed:
+	rte_fdt_path_free(base);
+	return -5;
+}
+
+/**
+ * Compute the length of the base using the delimiter '/'. An optional new top
+ * can be specified. If the top is NULL, only the base is examined. The NUL
+ * character is included.
+ */
+static size_t fdt_path_length(const struct rte_fdt_path *base, const char *top)
+{
+	size_t len = 0;
+
+	if (base == NULL && top == NULL)
+		return strlen("/") + 1;
+
+	while (base != NULL) {
+		RTE_VERIFY(base->name != NULL);
+		/* '/' + <name> */
+		len += 1 + strlen(base->name);
+		base = base->base;
+	}
+
+	if (top != NULL) {
+		/* '/' + <name> */
+		len += 1 + strlen(top);
+	}
+
+	return len + 1; /* append NUL */
+}
+
+char *rte_fdt_path_tostr(const struct rte_fdt_path *base, const char *top)
+{
+	const size_t len = fdt_path_length(base, top);
+	const struct rte_fdt_path *cur = base;
+	char *s;
+	char *p;
+
+	if (base == NULL && top == NULL)
+		return strdup("/");
+
+	s = malloc(len);
+	if (s == NULL)
+		return NULL;
+
+	if (base == NULL /* && top != NULL */) {
+		memcpy(s + 1, top, len - 2);
+		s[0] = '/';
+		s[len] = '\0';
+		return s;
+	}
+
+	/* find the bottom, the root component of the path */
+	while (cur->base != NULL)
+		cur = cur->base;
+
+	p = s;
+
+	/* copy the base from the bottom into the target string */
+	while (cur != NULL) {
+		size_t curlen = strlen(cur->name);
+
+		RTE_VERIFY(p - s + curlen + 1 < len);
+
+		p[0] = '/';
+		memcpy(p + 1, cur->name, curlen);
+		p += curlen + 1;
+
+		if (cur == base)
+			break;
+
+		cur = cur->top;
+	}
+
+	/* append top if exists */
+	if (top != NULL) {
+		size_t toplen = strlen(top);
+
+		RTE_VERIFY(p - s + toplen + 1 < len);
+
+		p[0] = '/';
+		memcpy(p + 1, top, toplen);
+		p += toplen + 1;
+	}
+
+	RTE_VERIFY(p - s + 1 == (off_t) len);
+	p[0] = '\0';
+
+	return s;
+}
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index e109361..e4b33b5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -61,6 +61,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_memory.c
 ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_xen_memory.c
 endif
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_fdt.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci.c
@@ -82,6 +83,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_fdt.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
@@ -113,6 +115,7 @@ CFLAGS_eal_lcore.o := -D_GNU_SOURCE
 CFLAGS_eal_thread.o := -D_GNU_SOURCE
 CFLAGS_eal_log.o := -D_GNU_SOURCE
 CFLAGS_eal_common_log.o := -D_GNU_SOURCE
+CFLAGS_eal_fdt.o := -D_GNU_SOURCE
 CFLAGS_eal_hugepage_info.o := -D_GNU_SOURCE
 CFLAGS_eal_pci.o := -D_GNU_SOURCE
 CFLAGS_eal_pci_uio.o := -D_GNU_SOURCE
diff --git a/lib/librte_eal/linuxapp/eal/eal_fdt.c b/lib/librte_eal/linuxapp/eal/eal_fdt.c
new file mode 100644
index 0000000..48c6b52
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_fdt.c
@@ -0,0 +1,336 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 RehiveTech. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of RehiveTech nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_byteorder.h>
+#include <rte_fdt.h>
+
+struct rte_fdt {
+	char *path;
+};
+
+struct rte_fdt *rte_fdt_open(const char *path)
+{
+	struct rte_fdt *fdt;
+	size_t pathlen;
+
+	if (path == NULL) {
+		path = "/proc/device-tree";
+		pathlen = strlen("/proc/device-tree");
+	} else {
+		pathlen = strlen(path);
+	}
+
+	fdt = malloc(sizeof(*fdt) + pathlen + 1);
+	if (fdt == NULL)
+		return NULL;
+
+	fdt->path = (char *) (fdt + 1);
+	memcpy(fdt->path, path, pathlen);
+	fdt->path[pathlen] = '\0';
+
+	return fdt;
+}
+
+void rte_fdt_close(struct rte_fdt *fdt)
+{
+	RTE_VERIFY(fdt != NULL);
+
+	fdt->path = NULL;
+	free(fdt);
+}
+
+static int concat_and_abspath(char path[PATH_MAX],
+		const char *p1, size_t p1len,
+		const char *p2, size_t p2len)
+{
+	char *tmppath;
+
+	tmppath = malloc(p1len + 1 + p2len + 1);
+	if (tmppath == NULL) {
+		RTE_LOG(ERR, EAL, "%s(): failed to malloc %zu B\n", __func__,
+				p1len + 1 + p2len + 1);
+		return -1;
+	}
+
+	memcpy(tmppath, p1, p1len);
+	tmppath[p1len] = '/';
+	memcpy(tmppath + p1len + 1, p2, p2len);
+	tmppath[p1len + p2len + 1] = '\0';
+
+	if (realpath(tmppath, path) == NULL) {
+		long _e = errno;
+		RTE_LOG(ERR, EAL, "%s(): realpath has failed for '%s'\n",
+				__func__, tmppath);
+		RTE_LOG(ERR, EAL, "reason: '%s'\n", strerror(_e));
+		free(tmppath);
+		return -2;
+	}
+
+	free(tmppath);
+	return 0;
+}
+
+static int fdt_path_open(struct rte_fdt *fdt, const struct rte_fdt_path *base,
+		const char *top)
+{
+	char *relpath = rte_fdt_path_tostr(base, top);
+	char path[PATH_MAX];
+	char root[PATH_MAX];
+	int fd;
+
+	RTE_VERIFY(fdt != NULL);
+	RTE_VERIFY(relpath[0] == '/');
+
+	if (relpath == NULL) {
+		RTE_LOG(ERR, EAL, "%s(): failed to convert "
+				"base path to string\n", __func__);
+		errno = ENOMEM;
+		return -1;
+	}
+
+	if (concat_and_abspath(path, fdt->path, strlen(fdt->path),
+				relpath + 1, strlen(relpath + 1))) {
+		RTE_LOG(ERR, EAL, "%s(): failed to derive absolute path from "
+				"the root ('%s') and the FDT path ('%s')\n",
+				__func__, fdt->path, relpath);
+		free(relpath);
+		errno = ENOMEM;
+		return -2;
+	}
+	free(relpath); /* not needed anymore */
+
+	/* ensure we have the fdt->path as a real and absolute path */
+	if (realpath(fdt->path, root) == NULL) {
+		long _e = errno;
+		RTE_LOG(ERR, EAL, "%s(): realpath of '%s' has failed",
+				__func__, fdt->path);
+		errno = _e;
+		return -3;
+	}
+
+	if (strstr(path, root) != path) {
+		/* We are out of the fdt->path */
+		RTE_LOG(ERR, EAL, "%s(): attempt to access out "
+				"of the root path: '%s'\n", __func__, path);
+		errno = EACCES;
+		return -4;
+	}
+
+	if ((fd = open(path, O_RDONLY)) < 0) {
+		RTE_LOG(ERR, EAL, "%s(): failed to open the FDT path '%s'\n",
+				__func__, path);
+		return -5;
+	}
+
+	return fd;
+}
+
+static ssize_t read_all(int fd, char *b, size_t bmax)
+{
+	size_t total = 0;
+
+	while (total < bmax) {
+		ssize_t rlen = read(fd, b + total, bmax - total);
+		if (rlen < 0)
+			return -1;
+
+		total += rlen;
+	}
+
+	return total;
+}
+
+static ssize_t fdt_path_read(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		void *b, size_t bmax)
+{
+	int fd;
+	struct stat st;
+	size_t goal;
+	ssize_t ret;
+
+	if ((fd = fdt_path_open(fdt, base, top)) < 0)
+		return -1;
+
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		return -2;
+	}
+
+	goal = st.st_size;
+	ret = read_all(fd, b, bmax > goal? goal : bmax);
+
+	close(fd);
+	return ret;
+}
+
+static ssize_t fdt_path_readx(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		void *v, size_t vmax, size_t vsize)
+{
+	size_t bmax = vmax * vsize;
+	ssize_t ret;
+
+	ret = fdt_path_read(fdt, base, top, v, bmax);
+	if (ret < 0)
+		return -1;
+
+	return ret / vsize;
+}
+
+ssize_t rte_fdt_path_read(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base,
+		const char *top, char *b, size_t blen)
+{
+	return fdt_path_read(fdt, base, top, b, blen);
+}
+
+ssize_t rte_fdt_path_read32(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		uint32_t *v, size_t vmax)
+{
+	ssize_t ret;
+	ssize_t i;
+
+	ret = fdt_path_readx(fdt, base, top, (void *) v, vmax, sizeof(*v));
+	if (ret <= 0)
+		return ret;
+
+	for (i = 0; i < ret; ++i)
+		v[i] = rte_be_to_cpu_32(v[i]);
+
+	return ret;
+}
+
+ssize_t rte_fdt_path_read64(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base, const char *top,
+		uint64_t *v, size_t vmax)
+{
+	ssize_t ret;
+	ssize_t i;
+
+	ret = fdt_path_readx(fdt, base, top, (void *) v, vmax, sizeof(*v));
+	if (ret <= 0)
+		return ret;
+
+	for (i = 0; i < ret; ++i)
+		v[i] = rte_be_to_cpu_64(v[i]);
+
+	return ret;
+
+}
+
+ssize_t rte_fdt_path_reads(struct rte_fdt *fdt,
+		const struct rte_fdt_path *base,
+		const char *top, char **s)
+{
+	int fd;
+	struct stat st;
+	size_t goal;
+	ssize_t ret;
+	char *b;
+
+	if ((fd = fdt_path_open(fdt, base, top)) < 0)
+		return -1;
+
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		return -2;
+	}
+
+	goal = st.st_size;
+
+	b = malloc(goal + 1);
+	if (b == NULL) {
+		close(fd);
+		return -3;
+	}
+
+
+	if ((ret = read_all(fd, b, goal)) < 0) {
+		free(b);
+		close(fd);
+		return -4;
+	}
+
+	b[goal] = '\0';
+
+	close(fd);
+	*s = b;
+	return ret;
+}
+
+int rte_fdt_path_walk(struct rte_fdt *fdt, const struct rte_fdt_path *base,
+		int (*f)(struct rte_fdt *, const struct rte_fdt_path *,
+			const char *, void *), void *context)
+{
+	int fd;
+	DIR *dir;
+	struct dirent entry;
+	struct dirent *cur = NULL;
+	int ret = 0;
+
+	RTE_VERIFY(f != NULL);
+
+	if ((fd = fdt_path_open(fdt, base, NULL)) < 0)
+		return -1;
+
+	dir = fdopendir(fd);
+	if (dir == NULL) {
+		close(fd);
+		return -2;
+	}
+
+	while ((readdir_r(dir, &entry, &cur)) == 0 && cur != NULL) {
+		if (!rte_fdt_path_is_valid(cur->d_name))
+			continue;
+
+		ret = f(fdt, base, cur->d_name, context);
+		if (ret != 0)
+			break;
+	}
+
+	closedir(dir); /* calls close() */
+	return ret;
+}
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 3/6] eal/fdt: test FDT API
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 1/6] eal/fdt: introduce Flattened Device Tree API Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 2/6] eal/fdt: implement FDT API for Linux Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 4/6] eal/fdt: add testing FDT of xgene-1 got from Linux runtime Jan Viktorin
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 app/test/Makefile   |   1 +
 app/test/test_fdt.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 271 insertions(+)
 create mode 100644 app/test/test_fdt.c

diff --git a/app/test/Makefile b/app/test/Makefile
index a4907d5..ce4ec263 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -103,6 +103,7 @@ SRCS-y += test_alarm.c
 SRCS-y += test_interrupts.c
 SRCS-y += test_version.c
 SRCS-y += test_func_reentrancy.c
+SRCS-y += test_fdt.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c
diff --git a/app/test/test_fdt.c b/app/test/test_fdt.c
new file mode 100644
index 0000000..7e6d331
--- /dev/null
+++ b/app/test/test_fdt.c
@@ -0,0 +1,270 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 RehiveTech. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of RehiveTech nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "test.h"
+
+#include <rte_fdt.h>
+
+static int test_fdt_path_is_valid(void)
+{
+	TEST_ASSERT(rte_fdt_path_is_valid("name"), "'name' must be valid");
+	TEST_ASSERT(rte_fdt_path_is_valid("comp@00ffabcd"),
+			"'comp@00ffabcd' must be valid");
+	TEST_ASSERT(rte_fdt_path_is_valid("#address-cells"),
+			"'#address-cells' must be valid");
+	TEST_ASSERT(rte_fdt_path_is_valid("#size-cells"),
+			"'#size-cells' must be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid(NULL), "NULL must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid("."), "'.' must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid(".."), "'..' must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid("/"), "'/' must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid("/name"),
+			"'/name' must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid("base/name"),
+			"'base/name' must not be valid");
+	TEST_ASSERT(!rte_fdt_path_is_valid("base/"),
+			"'base/' must not be valid");
+	return 0;
+}
+
+static int test_fdt_path_push_pop(void)
+{
+	struct rte_fdt_path *path = NULL;
+
+	path = rte_fdt_path_pushs(path, "amba");
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "amba"), "name must be 'amba'");
+	TEST_ASSERT_NULL(path->base, "base must be NULL");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+
+	path = rte_fdt_path_pushs(path, "ethernet@ffc00000");
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "ethernet@ffc00000"),
+			"name must be 'ethernet@ffc00000'");
+	TEST_ASSERT_NOT_NULL(path->base, "base must not be NULL");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+	TEST_ASSERT_EQUAL(path->base->top, path,
+			"base must point to current top");
+
+	path = rte_fdt_path_pushs(path, "name");
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "name"),
+			"name must be 'name'");
+	TEST_ASSERT_NOT_NULL(path->base, "base must not be NULL");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+	TEST_ASSERT_EQUAL(path->base->top, path,
+			"base must point to current top");
+
+	path = rte_fdt_path_pop(path);
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "ethernet@ffc00000"),
+			"name must be 'ethernet@ffc00000'");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+
+	path = rte_fdt_path_pushs(path, "compatible");
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "compatible"),
+			"name must be 'compatible'");
+	TEST_ASSERT_NOT_NULL(path->base, "base must not be NULL");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+	TEST_ASSERT_EQUAL(path->base->top, path,
+			"base must point to current top");
+
+	path = rte_fdt_path_pop(path);
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "ethernet@ffc00000"),
+			"name must be 'ethernet@ffc00000'");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+
+	path = rte_fdt_path_pop(path);
+	TEST_ASSERT_NOT_NULL(path, "path must not be NULL");
+	TEST_ASSERT(!strcmp(path->name, "amba"),
+			"name must be 'amba'");
+	TEST_ASSERT_NULL(path->top, "top must be NULL");
+
+	path = rte_fdt_path_pop(path);
+	TEST_ASSERT_NULL(path, "path must be NULL");
+
+	return 0;
+}
+
+static int fdt_path_equal(const struct rte_fdt_path *a,
+		const struct rte_fdt_path *b)
+{
+	while (a != NULL && b != NULL) {
+		if (strcmp(a->name, b->name))
+			return 0;
+
+		a = a->base;
+		b = b->base;
+	}
+
+	if (a != b) /* both must be NULL */
+		return 0;
+
+	return 1;
+}
+
+static int test_fdt_path_parse(void)
+{
+	const char *p0  = "/";
+	const char *p1  = "/amba";
+	const char *p2  = "/amba/ethernet@ffc00000";
+	const char *p3  = "/amba/ethernet@ffc00000/compatible";
+	const char *p4  = "/amba/./xxx";
+	const char *p5  = "/amba/./xxx/.";
+	const char *p6  = "/amba/../xxx/..";
+	const char *p7  = "..";
+	const char *p8  = "/..";
+	const char *p9  = "";
+	const char *p10 = NULL;
+
+	struct rte_fdt_path *test = NULL;
+	struct rte_fdt_path *tmp;
+
+	// parse p0
+
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p0), 0,
+			"failed to parse p0");
+	TEST_ASSERT_NULL(tmp, "tmp must be NULL");
+
+	// parse p1
+
+	test = rte_fdt_path_pushs(test, "amba");
+	TEST_ASSERT_NOT_NULL(test, "push failed for 'amba'");
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p1), 0,
+			"failed to parse p1");
+	TEST_ASSERT_NOT_NULL(tmp, "tmp must not be NULL");
+	TEST_ASSERT(fdt_path_equal(test, tmp),
+			"parsed p1 does not match the constructed path");
+	tmp = rte_fdt_path_free(tmp);
+
+	// parse p2
+
+	test = rte_fdt_path_pushs(test, "ethernet@ffc00000");
+	TEST_ASSERT_NOT_NULL(test, "push failed for 'ethernet@ffc00000'");
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p2), 0,
+			"failed to parse p2");
+	TEST_ASSERT_NOT_NULL(tmp, "tmp must not be NULL");
+	TEST_ASSERT(fdt_path_equal(test, tmp),
+			"parsed p2 does not match the constructed path");
+	tmp = rte_fdt_path_free(tmp);
+
+	// parse p3
+
+	test = rte_fdt_path_pushs(test, "compatible");
+	TEST_ASSERT_NOT_NULL(test, "push failed for 'compatible'");
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p3), 0,
+			"failed to parse p3");
+	TEST_ASSERT_NOT_NULL(tmp, "tmp must not be NULL");
+	TEST_ASSERT(fdt_path_equal(test, tmp),
+			"parsed p3 does not match the constructed path");
+	tmp = rte_fdt_path_free(tmp);
+
+	// parse p4
+
+	test = rte_fdt_path_pop(test); /* pop compatible */
+	test = rte_fdt_path_pop(test); /* pop ethernet@ffc00000 */
+
+	test = rte_fdt_path_pushs(test, "xxx");
+	TEST_ASSERT_NOT_NULL(test, "push failed for 'xxx'");
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p4), 0,
+			"failed to parse p4");
+	TEST_ASSERT_NOT_NULL(tmp, "tmp must not be NULL");
+	TEST_ASSERT(fdt_path_equal(test, tmp),
+			"parsed p4 does not match the constructed path");
+	tmp = rte_fdt_path_free(tmp);
+
+	// parse p5
+
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p5), 0,
+			"failed to parse p5");
+	TEST_ASSERT_NOT_NULL(tmp, "tmp must not be NULL");
+	TEST_ASSERT(fdt_path_equal(test, tmp),
+			"parsed p5 does not match the constructed path");
+	tmp = rte_fdt_path_free(tmp);
+
+	// parse p6
+
+	test = rte_fdt_path_free(test);
+
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p6), 0,
+			"failed to parse p6");
+	TEST_ASSERT_NULL(tmp, "tmp must be NULL");
+
+	// parse p7
+
+	TEST_ASSERT_NOT_EQUAL(rte_fdt_path_parse(&tmp, p7), 0,
+			"parse p7 must fail");
+	// parse p8
+
+	TEST_ASSERT_EQUAL(rte_fdt_path_parse(&tmp, p8), 0,
+			"failed to parse p8");
+	TEST_ASSERT_NULL(tmp, "tmp must be NULL");
+
+	// parse p9
+
+	TEST_ASSERT_NOT_EQUAL(rte_fdt_path_parse(&tmp, p9), 0,
+			"parse p9 must fail");
+
+	// parse p10
+
+	TEST_ASSERT_NOT_EQUAL(rte_fdt_path_parse(&tmp, p10), 0,
+			"parse p10 must fail");
+
+	return 0;
+}
+
+static int test_fdt(void)
+{
+	if (test_fdt_path_is_valid())
+		return -1;
+
+	if (test_fdt_path_push_pop())
+		return -1;
+
+	if (test_fdt_path_parse())
+		return -1;
+
+	return 0;
+}
+
+static struct test_command fdt_cmd = {
+	.command = "fdt_autotest",
+	.callback = test_fdt,
+};
+REGISTER_TEST_COMMAND(fdt_cmd);
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 4/6] eal/fdt: add testing FDT of xgene-1 got from Linux runtime
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (2 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 3/6] eal/fdt: test FDT API Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test FDT for Linux on real data source Jan Viktorin
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 app/test/linux-fdt/xgene1/#address-cells                   | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/#size-cells                      | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/compatible                       | Bin 0 -> 28 bytes
 app/test/linux-fdt/xgene1/model                            | Bin 0 -> 25 bytes
 .../xgene1/soc/ethernet@17020000/local-mac-address         | Bin 0 -> 6 bytes
 app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg        | Bin 0 -> 48 bytes
 6 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 app/test/linux-fdt/xgene1/#address-cells
 create mode 100644 app/test/linux-fdt/xgene1/#size-cells
 create mode 100644 app/test/linux-fdt/xgene1/compatible
 create mode 100644 app/test/linux-fdt/xgene1/model
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/local-mac-address
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg

diff --git a/app/test/linux-fdt/xgene1/#address-cells b/app/test/linux-fdt/xgene1/#address-cells
new file mode 100644
index 0000000000000000000000000000000000000000..b6a8ef3e7ca7c398cd8f65bb1e21a23c0d251536
GIT binary patch
literal 4
LcmZQzU|<3O00sa9

literal 0
HcmV?d00001

diff --git a/app/test/linux-fdt/xgene1/#size-cells b/app/test/linux-fdt/xgene1/#size-cells
new file mode 100644
index 0000000000000000000000000000000000000000..b6a8ef3e7ca7c398cd8f65bb1e21a23c0d251536
GIT binary patch
literal 4
LcmZQzU|<3O00sa9

literal 0
HcmV?d00001

diff --git a/app/test/linux-fdt/xgene1/compatible b/app/test/linux-fdt/xgene1/compatible
new file mode 100644
index 0000000000000000000000000000000000000000..97cc3c0625df34ef0ddf2d8583d091b2b99d4375
GIT binary patch
literal 28
hcmYc+$koX$EiOsSOJ_&~vMbV4^HOz-OY)0y8335~3QYh2

literal 0
HcmV?d00001

diff --git a/app/test/linux-fdt/xgene1/model b/app/test/linux-fdt/xgene1/model
new file mode 100644
index 0000000000000000000000000000000000000000..ad6d38ed6cae1cc448317551224940a5ea0bef1d
GIT binary patch
literal 25
gcmZ<^@KuP=bx+MpRq!n>E=kNwS4hfFEJ|Sj0A`j5DgXcg

literal 0
HcmV?d00001

diff --git a/app/test/linux-fdt/xgene1/soc/ethernet@17020000/local-mac-address b/app/test/linux-fdt/xgene1/soc/ethernet@17020000/local-mac-address
new file mode 100644
index 0000000000000000000000000000000000000000..3a118c46eee3501e4ba2a8ea3e7dd2240e80ceed
GIT binary patch
literal 6
NcmZP&wCakg000CH0jK}~

literal 0
HcmV?d00001

diff --git a/app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg b/app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg
new file mode 100644
index 0000000000000000000000000000000000000000..620a8efe117328cf2b4ca5283386c3ab2cf09d0d
GIT binary patch
literal 48
ccmZQzU|<ku0um5l0HWZ0Mu;Gs&%mGn01m+bod5s;

literal 0
HcmV?d00001

-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 5/6] eal/fdt: test FDT for Linux on real data source
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (3 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 4/6] eal/fdt: add testing FDT of xgene-1 got from Linux runtime Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test Linux implementation on xgene-1 FDT Jan Viktorin
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

The test assumes a partial copy of a /proc/device-tree from the xgene-1 Linux
runtime located at $(PWD)/linux-dt/xgene-1.

We introduce tests of:
* rte_fdt_open/close
* rte_fdt_path_read
* rte_fdt_path_walk

It was not possible to implement those with no real device-tree available.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 app/test/test_fdt.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/app/test/test_fdt.c b/app/test/test_fdt.c
index 7e6d331..63e131d 100644
--- a/app/test/test_fdt.c
+++ b/app/test/test_fdt.c
@@ -37,8 +37,27 @@
 
 #include "test.h"
 
+#include <rte_common.h>
 #include <rte_fdt.h>
 
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_fdt_open_close(void)
+{
+	struct rte_fdt *fdt;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+	rte_fdt_close(fdt);
+	return 0;
+}
+#else
+static int test_fdt_open_close(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
 static int test_fdt_path_is_valid(void)
 {
 	TEST_ASSERT(rte_fdt_path_is_valid("name"), "'name' must be valid");
@@ -249,8 +268,197 @@ static int test_fdt_path_parse(void)
 	return 0;
 }
 
+static int test_fdt_path_read_common(struct rte_fdt *fdt)
+{
+	struct rte_fdt_path *path = NULL;
+	ssize_t len;
+	char *str;
+	uint32_t u32;
+
+	/* reads string from /model */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/model"),
+			"failed to parse '/model'");
+	len = rte_fdt_path_reads(fdt, path, NULL, &str);
+	TEST_ASSERT_EQUAL(len, 25,
+			"unexpected length (%zd) of '/model'", len);
+	TEST_ASSERT_SUCCESS(strcmp(str, "APM X-Gene Mustang board"),
+			"unexpected content of '/model': '%s'", str);
+	free(str);
+	rte_fdt_path_free(path);
+
+	/* reads string from /compatible */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/compatible"),
+			"failed to parse '/compatible'");
+	len = rte_fdt_path_reads(fdt, path, NULL, &str);
+	TEST_ASSERT_EQUAL(len, 28,
+			"unexpected length (%zd) of '/compatible'", len);
+	TEST_ASSERT_SUCCESS(strcmp(str, "apm,mustang\0apm,xgene-storm"),
+			"unexpected content(1) of '/compatible': '%s'", str);
+	TEST_ASSERT_SUCCESS(strcmp(str + 12, "apm,xgene-storm"),
+			"unexpected content(2) of '/compatible': '%s'", str);
+	free(str);
+	rte_fdt_path_free(path);
+
+	/* reads string from /#address-cells */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/#address-cells"),
+			"failed to parse '/#address-cells'");
+	len = rte_fdt_path_read32(fdt, path, NULL, &u32, 1);
+	TEST_ASSERT_EQUAL(len, 1, "failed to read "
+			"'/#address-cells': %zd", len);
+	TEST_ASSERT_EQUAL(u32, 2, "unexpected value of "
+			"'/#address-cells': %zu", (size_t) u32);
+	rte_fdt_path_free(path);
+
+	/* reads string from /#size-cells */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/#size-cells"),
+			"failed to parse '/#size-cells'");
+	len = rte_fdt_path_read32(fdt, path, NULL, &u32, 1);
+	TEST_ASSERT_EQUAL(len, 1, "failed to read "
+			"'/#size-cells': %zd", len);
+	TEST_ASSERT_EQUAL(u32, 2, "unexpected value of "
+			"'/#size-cells': %zu", (size_t) u32);
+	rte_fdt_path_free(path);
+
+	return 0;
+}
+
+static int test_fdt_xgene1_ethernet(struct rte_fdt *fdt)
+{
+	struct rte_fdt_path *base;
+	ssize_t len;
+	uint64_t reg[6];
+	char mac[6];
+	ssize_t i;
+	const char e17020000_mac[] = {
+		0x00, 0x11, 0x3a, 0x8a, 0x5a, 0x78
+	};
+
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&base,
+				"/soc/ethernet@17020000"),
+			"failed to parse '/soc/ethernet@17020000'");
+	len = rte_fdt_path_read64(fdt, base, "reg", reg, 6);
+	TEST_ASSERT_EQUAL(len, 6, "unexpected length of 'reg': %zd", len);
+
+	TEST_ASSERT_EQUAL(reg[0], 0x17020000, "unexpected value of "
+			"reg[0]: %zx", reg[0]);
+	TEST_ASSERT_EQUAL(reg[1], 0x00000030, "unexpected value of "
+			"reg[1]: %zx", reg[1]);
+	TEST_ASSERT_EQUAL(reg[2], 0x17020000, "unexpected value of "
+			"reg[2]: %zx", reg[2]);
+	TEST_ASSERT_EQUAL(reg[3], 0x00010000, "unexpected value of "
+			"reg[3]: %zx", reg[3]);
+	TEST_ASSERT_EQUAL(reg[4], 0x17020000, "unexpected value of "
+			"reg[4]: %zx", reg[4]);
+	TEST_ASSERT_EQUAL(reg[5], 0x00000020, "unexpected value of "
+			"reg[5]: %zx", reg[5]);
+
+	len = rte_fdt_path_read(fdt, base, "local-mac-address", mac, 6);
+	TEST_ASSERT_EQUAL(len, 6, "unexpected length of "
+			"'local-mac-address': %zd", len);
+	for (i = 0; i < len; ++i) {
+		int v = mac[i];
+		int exp = e17020000_mac[i];
+		TEST_ASSERT_EQUAL(v, exp, "unexpected mac[%zu]: %x\n", i, v);
+	}
+
+	rte_fdt_path_free(base);
+	return 0;
+}
+
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_fdt_path_read(void)
+{
+	int ret;
+	struct rte_fdt *fdt;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+
+	ret = test_fdt_path_read_common(fdt);
+	if (ret)
+		goto fail;
+
+	ret = test_fdt_xgene1_ethernet(fdt);
+	if (ret)
+		goto fail;
+
+fail:
+	rte_fdt_close(fdt);
+	return ret;
+}
+#else
+static int test_fdt_path_read(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_walk(__rte_unused struct rte_fdt *fdt,
+		__rte_unused const struct rte_fdt_path *path,
+		const char *top, void *context)
+{
+	struct {
+		int seen;
+		const char *name;
+	} *expect = context;
+	int i;
+
+	for (i = 0; i < 5; ++i) {
+		if (!strcmp(top, expect[i].name)) {
+			expect[i].seen += 1;
+			return 0;
+		}
+	}
+
+	printf("unexpected top: '%s'\n", top);
+	return 2; /* stop walking, unexpected top */
+}
+
+static int test_fdt_path_walk(void)
+{
+	int ret;
+	struct rte_fdt *fdt;
+	struct {
+		int seen;
+		const char *name;
+	} expect[] = {
+		{ 0, "#address-cells" },
+		{ 0, "compatible" },
+		{ 0, "model" },
+		{ 0, "#size-cells" },
+		{ 0, "soc" },
+	};
+	int i;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+
+	ret = rte_fdt_path_walk(fdt, NULL, test_walk, expect);
+	TEST_ASSERT_SUCCESS(ret, "walk has failed: %d", ret);
+
+	for (i = 0; i < 5; ++i) {
+		TEST_ASSERT_EQUAL(expect[i].seen, 1, "unexpected value of "
+				"seen for '%s' (%u)", expect[i].name, i);
+	}
+
+	rte_fdt_close(fdt);
+	return 0;
+}
+#else
+static int test_fdt_path_walk(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
 static int test_fdt(void)
 {
+	if (test_fdt_open_close())
+		return -1;
+
 	if (test_fdt_path_is_valid())
 		return -1;
 
@@ -260,6 +468,12 @@ static int test_fdt(void)
 	if (test_fdt_path_parse())
 		return -1;
 
+	if (test_fdt_path_read())
+		return -1;
+
+	if (test_fdt_path_walk())
+		return -1;
+
 	return 0;
 }
 
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 5/6] eal/fdt: test Linux implementation on xgene-1 FDT
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (4 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test FDT for Linux on real data source Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 6/6] eal/fdt: export for dpdk 16.07 Jan Viktorin
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

The test assumes a partial copy of a /proc/device-tree from the xgene-1 Linux
runtime located at $(PWD)/linux-dt/xgene-1.

We introduce tests of:
* rte_fdt_open/close
* rte_fdt_path_read
* rte_fdt_path_walk

It was not possible to implement those with no real device-tree available.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 app/test/test_fdt.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/app/test/test_fdt.c b/app/test/test_fdt.c
index 7e6d331..9675f69 100644
--- a/app/test/test_fdt.c
+++ b/app/test/test_fdt.c
@@ -37,8 +37,27 @@
 
 #include "test.h"
 
+#include <rte_common.h>
 #include <rte_fdt.h>
 
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_fdt_open_close(void)
+{
+	struct rte_fdt *fdt;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+	rte_fdt_close(fdt);
+	return 0;
+}
+#else
+static int test_fdt_open_close(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
 static int test_fdt_path_is_valid(void)
 {
 	TEST_ASSERT(rte_fdt_path_is_valid("name"), "'name' must be valid");
@@ -249,8 +268,197 @@ static int test_fdt_path_parse(void)
 	return 0;
 }
 
+static int test_fdt_path_read_common(struct rte_fdt *fdt)
+{
+	struct rte_fdt_path *path = NULL;
+	ssize_t len;
+	char *str;
+	uint32_t u32;
+
+	/* reads string from /model */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/model"),
+			"failed to parse '/model'");
+	len = rte_fdt_path_reads(fdt, path, NULL, &str);
+	TEST_ASSERT_EQUAL(len, 25,
+			"unexpected length (%zd) of '/model'", len);
+	TEST_ASSERT_SUCCESS(strcmp(str, "APM X-Gene Mustang board"),
+			"unexpected content of '/model': '%s'", str);
+	free(str);
+	rte_fdt_path_free(path);
+
+	/* reads string from /compatible */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/compatible"),
+			"failed to parse '/compatible'");
+	len = rte_fdt_path_reads(fdt, path, NULL, &str);
+	TEST_ASSERT_EQUAL(len, 28,
+			"unexpected length (%zd) of '/compatible'", len);
+	TEST_ASSERT_SUCCESS(strcmp(str, "apm,mustang\0apm,xgene-storm"),
+			"unexpected content(1) of '/compatible': '%s'", str);
+	TEST_ASSERT_SUCCESS(strcmp(str + 12, "apm,xgene-storm"),
+			"unexpected content(2) of '/compatible': '%s'", str);
+	free(str);
+	rte_fdt_path_free(path);
+
+	/* reads string from /#address-cells */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/#address-cells"),
+			"failed to parse '/#address-cells'");
+	len = rte_fdt_path_read32(fdt, path, NULL, &u32, 1);
+	TEST_ASSERT_EQUAL(len, 1, "failed to read "
+			"'/#address-cells': %zd", len);
+	TEST_ASSERT_EQUAL(u32, 2, "unexpected value of "
+			"'/#address-cells': %zu", (size_t) u32);
+	rte_fdt_path_free(path);
+
+	/* reads string from /#size-cells */
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&path, "/#size-cells"),
+			"failed to parse '/#size-cells'");
+	len = rte_fdt_path_read32(fdt, path, NULL, &u32, 1);
+	TEST_ASSERT_EQUAL(len, 1, "failed to read "
+			"'/#size-cells': %zd", len);
+	TEST_ASSERT_EQUAL(u32, 2, "unexpected value of "
+			"'/#size-cells': %zu", (size_t) u32);
+	rte_fdt_path_free(path);
+
+	return 0;
+}
+
+static int test_fdt_xgene1_ethernet(struct rte_fdt *fdt)
+{
+	struct rte_fdt_path *base;
+	ssize_t len;
+	uint64_t reg[6];
+	char mac[6];
+	ssize_t i;
+	const char e17020000_mac[] = {
+		0x00, 0x11, 0x3a, 0x8a, 0x5a, 0x78
+	};
+
+	TEST_ASSERT_SUCCESS(rte_fdt_path_parse(&base,
+				"/soc/ethernet@17020000"),
+			"failed to parse '/soc/ethernet@17020000'");
+	len = rte_fdt_path_read64(fdt, base, "reg", reg, 6);
+	TEST_ASSERT_EQUAL(len, 6, "unexpected length of 'reg': %zd", len);
+
+	TEST_ASSERT_EQUAL(reg[0], 0x17020000, "unexpected value of "
+			"reg[0]: %zx", (size_t) reg[0]);
+	TEST_ASSERT_EQUAL(reg[1], 0x00000030, "unexpected value of "
+			"reg[1]: %zx", (size_t) reg[1]);
+	TEST_ASSERT_EQUAL(reg[2], 0x17020000, "unexpected value of "
+			"reg[2]: %zx", (size_t) reg[2]);
+	TEST_ASSERT_EQUAL(reg[3], 0x00010000, "unexpected value of "
+			"reg[3]: %zx", (size_t) reg[3]);
+	TEST_ASSERT_EQUAL(reg[4], 0x17020000, "unexpected value of "
+			"reg[4]: %zx", (size_t) reg[4]);
+	TEST_ASSERT_EQUAL(reg[5], 0x00000020, "unexpected value of "
+			"reg[5]: %zx", (size_t) reg[5]);
+
+	len = rte_fdt_path_read(fdt, base, "local-mac-address", mac, 6);
+	TEST_ASSERT_EQUAL(len, 6, "unexpected length of "
+			"'local-mac-address': %zd", len);
+	for (i = 0; i < len; ++i) {
+		int v = mac[i];
+		int exp = e17020000_mac[i];
+		TEST_ASSERT_EQUAL(v, exp, "unexpected mac[%zu]: %x\n", i, v);
+	}
+
+	rte_fdt_path_free(base);
+	return 0;
+}
+
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_fdt_path_read(void)
+{
+	int ret;
+	struct rte_fdt *fdt;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+
+	ret = test_fdt_path_read_common(fdt);
+	if (ret)
+		goto fail;
+
+	ret = test_fdt_xgene1_ethernet(fdt);
+	if (ret)
+		goto fail;
+
+fail:
+	rte_fdt_close(fdt);
+	return ret;
+}
+#else
+static int test_fdt_path_read(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int test_walk(__rte_unused struct rte_fdt *fdt,
+		__rte_unused const struct rte_fdt_path *path,
+		const char *top, void *context)
+{
+	struct {
+		int seen;
+		const char *name;
+	} *expect = context;
+	int i;
+
+	for (i = 0; i < 5; ++i) {
+		if (!strcmp(top, expect[i].name)) {
+			expect[i].seen += 1;
+			return 0;
+		}
+	}
+
+	printf("unexpected top: '%s'\n", top);
+	return 2; /* stop walking, unexpected top */
+}
+
+static int test_fdt_path_walk(void)
+{
+	int ret;
+	struct rte_fdt *fdt;
+	struct {
+		int seen;
+		const char *name;
+	} expect[] = {
+		{ 0, "#address-cells" },
+		{ 0, "compatible" },
+		{ 0, "model" },
+		{ 0, "#size-cells" },
+		{ 0, "soc" },
+	};
+	int i;
+
+	fdt = rte_fdt_open("linux-fdt/xgene1");
+	TEST_ASSERT_NOT_NULL(fdt, "failed to open linux-fdt/xgene1");
+
+	ret = rte_fdt_path_walk(fdt, NULL, test_walk, expect);
+	TEST_ASSERT_SUCCESS(ret, "walk has failed: %d", ret);
+
+	for (i = 0; i < 5; ++i) {
+		TEST_ASSERT_EQUAL(expect[i].seen, 1, "unexpected value of "
+				"seen for '%s' (%u)", expect[i].name, i);
+	}
+
+	rte_fdt_close(fdt);
+	return 0;
+}
+#else
+static int test_fdt_path_walk(void)
+{
+	printf("The %s is not implemented for this platform\n", __func__);
+	return 0;
+}
+#endif
+
 static int test_fdt(void)
 {
+	if (test_fdt_open_close())
+		return -1;
+
 	if (test_fdt_path_is_valid())
 		return -1;
 
@@ -260,6 +468,12 @@ static int test_fdt(void)
 	if (test_fdt_path_parse())
 		return -1;
 
+	if (test_fdt_path_read())
+		return -1;
+
+	if (test_fdt_path_walk())
+		return -1;
+
 	return 0;
 }
 
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 6/6] eal/fdt: export for dpdk 16.07
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (5 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test Linux implementation on xgene-1 FDT Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-26  1:12 ` [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
  2016-03-28  2:43 ` Jianbo Liu
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 12503ef..0c54859 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -154,3 +154,23 @@ DPDK_16.04 {
 	rte_eal_primary_proc_alive;
 
 } DPDK_2.2;
+
+DPDK_16.07 {
+	global:
+
+	rte_fdt_open;
+	rte_fdt_close;
+	rte_fdt_path_is_valid;
+	rte_fdt_path_pushs;
+	rte_fdt_path_pop;
+	rte_fdt_path_dup;
+	rte_fdt_path_free;
+	rte_fdt_path_parse;
+	rte_fdt_path_tostr;
+	rte_fdt_path_read;
+	rte_fdt_path_read32;
+	rte_fdt_path_read64;
+	rte_fdt_path_reads;
+	rte_fdt_path_walk;
+
+} DPDK_16.07;
-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (6 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 6/6] eal/fdt: export for dpdk 16.07 Jan Viktorin
@ 2016-03-26  1:12 ` Jan Viktorin
  2016-03-28  2:43 ` Jianbo Liu
  8 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-26  1:12 UTC (permalink / raw)
  To: dev
  Cc: Thomas Monjalon, Stephen Hemminger, Keith Wiles, david.marchand,
	jianbo.liu, jerin.jacob, bruce.richardson, Jan Viktorin

Hello,

while extending the DPDK by a kind of platform devices (for the 16.07), an
access to the FDT might be necessary (or at least very helpful). This patch
series for 16.07 introduces an approach to solve this topic.

The API is designed from scratch and there is only the Linux backend for it.
The Linux backend can read and traverse the /proc/device-tree structure. The
API, however, stays as independent as possible. It is possible to:

* open the FDT in a platform independent way (rte_fdt_open/close)
* define a path in the FDT in an abstract way (rte_fdt_path)
* read strings, 32 and 64 bit values, a binary content (rte_fdt_path_readX)
* walk the FDT structure from a selected point (rte_fdt_path_walk)

I've included unit tests of the API and of the Linux implemention. Some basic
API tests are introduced in the patch 3. Then a simplified device-tree file
structure is added together with more tests testing the Linux backend (4,5).
I've left those 3 patches separated for now but I think they can be aggregated
into a single patch later.

Here, I've encounter an issue. The testing FDT files (app/test/linux-fdt) need
to be copied (or linked) to the working directory of the _test_ executable. I
have no idea, how to integrate such logic into the build system.

The API provides a very limited set of access functions. I think, it's as
minimalistic as possible while enabling all necessary operations a PMD driver
would need. However, some higher level functions would be helpful, too.

The patch series is still missing some bits (eg. better error logging).

Any comments and suggestions are welcome...

Regards
Jan

Jan Viktorin (6):
  eal/fdt: introduce Flattened Device Tree API
  eal/fdt: implement FDT API for Linux
  eal/fdt: test FDT API
  eal/fdt: add testing FDT of xgene-1 got from Linux runtime
  eal/fdt: test FDT for Linux on real data source
  eal/fdt: export for dpdk 16.07

 app/test/Makefile                                  |   1 +
 app/test/linux-fdt/xgene1/#address-cells           | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/#size-cells              | Bin 0 -> 4 bytes
 app/test/linux-fdt/xgene1/compatible               | Bin 0 -> 28 bytes
 app/test/linux-fdt/xgene1/model                    | Bin 0 -> 25 bytes
 .../xgene1/soc/ethernet@17020000/local-mac-address | Bin 0 -> 6 bytes
 .../linux-fdt/xgene1/soc/ethernet@17020000/reg     | Bin 0 -> 48 bytes
 app/test/test_fdt.c                                | 484 +++++++++++++++++++++
 lib/librte_eal/common/Makefile                     |   2 +-
 lib/librte_eal/common/eal_common_fdt.c             | 317 ++++++++++++++
 lib/librte_eal/common/include/rte_fdt.h            | 185 ++++++++
 lib/librte_eal/linuxapp/eal/Makefile               |   3 +
 lib/librte_eal/linuxapp/eal/eal_fdt.c              | 336 ++++++++++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |  20 +
 14 files changed, 1347 insertions(+), 1 deletion(-)
 create mode 100644 app/test/linux-fdt/xgene1/#address-cells
 create mode 100644 app/test/linux-fdt/xgene1/#size-cells
 create mode 100644 app/test/linux-fdt/xgene1/compatible
 create mode 100644 app/test/linux-fdt/xgene1/model
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/local-mac-address
 create mode 100644 app/test/linux-fdt/xgene1/soc/ethernet@17020000/reg
 create mode 100644 app/test/test_fdt.c
 create mode 100644 lib/librte_eal/common/eal_common_fdt.c
 create mode 100644 lib/librte_eal/common/include/rte_fdt.h
 create mode 100644 lib/librte_eal/linuxapp/eal/eal_fdt.c

-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK
  2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
                   ` (7 preceding siblings ...)
  2016-03-26  1:12 ` [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
@ 2016-03-28  2:43 ` Jianbo Liu
  2016-03-29 10:34   ` Jan Viktorin
  8 siblings, 1 reply; 11+ messages in thread
From: Jianbo Liu @ 2016-03-28  2:43 UTC (permalink / raw)
  To: Jan Viktorin
  Cc: dev, Thomas Monjalon, Stephen Hemminger, Keith Wiles,
	david.marchand, Jerin Jacob, Bruce Richardson

On 26 March 2016 at 09:12, Jan Viktorin <viktorin@rehivetech.com> wrote:
> Hello,
>
> while extending the DPDK by a kind of platform devices (for the 16.07), an
> access to the FDT might be necessary (or at least very helpful). This patch
> series for 16.07 introduces an approach to solve this topic.
>
> The API is designed from scratch and there is only the Linux backend for it.
> The Linux backend can read and traverse the /proc/device-tree structure. The
> API, however, stays as independent as possible. It is possible to:
>
> * open the FDT in a platform independent way (rte_fdt_open/close)
> * define a path in the FDT in an abstract way (rte_fdt_path)
> * read strings, 32 and 64 bit values, a binary content (rte_fdt_path_readX)
> * walk the FDT structure from a selected point (rte_fdt_path_walk)
>
> I've included unit tests of the API and of the Linux implemention. Some basic
> API tests are introduced in the patch 3. Then a simplified device-tree file
> structure is added together with more tests testing the Linux backend (4,5).
> I've left those 3 patches separated for now but I think they can be aggregated
> into a single patch later.
>
> Here, I've encounter an issue. The testing FDT files (app/test/linux-fdt) need
> to be copied (or linked) to the working directory of the _test_ executable. I
> have no idea, how to integrate such logic into the build system.
>
Why not store FDT files in the code, for example, as a group of binary arrays?
When test is executed, it firstly creates the files in the working
directory from those arrays.

Jianbo

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK
  2016-03-28  2:43 ` Jianbo Liu
@ 2016-03-29 10:34   ` Jan Viktorin
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Viktorin @ 2016-03-29 10:34 UTC (permalink / raw)
  To: Jianbo Liu
  Cc: dev, Thomas Monjalon, Stephen Hemminger, Keith Wiles,
	david.marchand, Jerin Jacob, Bruce Richardson

On Mon, 28 Mar 2016 10:43:00 +0800
Jianbo Liu <jianbo.liu@linaro.org> wrote:

> On 26 March 2016 at 09:12, Jan Viktorin <viktorin@rehivetech.com> wrote:
> > Hello,
> >
> > while extending the DPDK by a kind of platform devices (for the 16.07), an
> > access to the FDT might be necessary (or at least very helpful). This patch
> > series for 16.07 introduces an approach to solve this topic.
> >
> > The API is designed from scratch and there is only the Linux backend for it.
> > The Linux backend can read and traverse the /proc/device-tree structure. The
> > API, however, stays as independent as possible. It is possible to:
> >
> > * open the FDT in a platform independent way (rte_fdt_open/close)
> > * define a path in the FDT in an abstract way (rte_fdt_path)
> > * read strings, 32 and 64 bit values, a binary content (rte_fdt_path_readX)
> > * walk the FDT structure from a selected point (rte_fdt_path_walk)
> >
> > I've included unit tests of the API and of the Linux implemention. Some basic
> > API tests are introduced in the patch 3. Then a simplified device-tree file
> > structure is added together with more tests testing the Linux backend (4,5).
> > I've left those 3 patches separated for now but I think they can be aggregated
> > into a single patch later.
> >
> > Here, I've encounter an issue. The testing FDT files (app/test/linux-fdt) need
> > to be copied (or linked) to the working directory of the _test_ executable. I
> > have no idea, how to integrate such logic into the build system.
> >  
> Why not store FDT files in the code, for example, as a group of binary arrays?
> When test is executed, it firstly creates the files in the working
> directory from those arrays.

Do you know some working solution of this? I am thinking of something
like objcopy of file contents, then link it to the test application.

This about extending the "test framework" a bit. Would somebody else
use such a feature?

Anyway, thank you for this idea.

Jan

> 
> Jianbo



-- 
   Jan Viktorin                  E-mail: Viktorin@RehiveTech.com
   System Architect              Web:    www.RehiveTech.com
   RehiveTech
   Brno, Czech Republic

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-03-29 10:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-26  1:12 [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 1/6] eal/fdt: introduce Flattened Device Tree API Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 2/6] eal/fdt: implement FDT API for Linux Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 3/6] eal/fdt: test FDT API Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 4/6] eal/fdt: add testing FDT of xgene-1 got from Linux runtime Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test FDT for Linux on real data source Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 5/6] eal/fdt: test Linux implementation on xgene-1 FDT Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 6/6] eal/fdt: export for dpdk 16.07 Jan Viktorin
2016-03-26  1:12 ` [dpdk-dev] [RFC 0/6] Flattened Device Tree access from DPDK Jan Viktorin
2016-03-28  2:43 ` Jianbo Liu
2016-03-29 10:34   ` Jan Viktorin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).