[PATCH 1/2] libfdt: Improve fdt_get_phandle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Given a node offset, the function fdt_get_phandle finds and returns the
phandle property defined in this node.

The current implementation first tries to read the "phandle" property,
then, should this not succeed, tries to read the "linux,phandle" property
afterwards (both by using the fdt_getprop function), and returns either
one if it is found.

This means that we potentially iterate over the properties of the node
twice (if the neither the "phandle", nor the "linux,phandle" property is
found).

Instead of doing this, iterate once over the nodes' properties, and
check each one if it is equal to either "phandle" or "linux,phandle",
and return the value in either case. Hence, we only iterate over the
properties exactly once.

Signed-off-by: Mario Six <mario.six@xxxxxxxx>
---
 libfdt/fdt_ro.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index dfb3236..7d049fb 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -424,19 +424,32 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
 
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
-	const fdt32_t *php;
+	const fdt32_t *php = NULL;
 	int len;
+	int offset;
 
-	/* FIXME: This is a bit sub-optimal, since we potentially scan
-	 * over all the properties twice. */
-	php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
-	if (!php || (len != sizeof(*php))) {
-		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
-		if (!php || (len != sizeof(*php)))
-			return 0;
+	for (offset = fdt_first_property_offset(fdt, nodeoffset);
+	     (offset >= 0);
+	     (offset = fdt_next_property_offset(fdt, offset))) {
+		const struct fdt_property *prop;
+
+		if (!(prop = fdt_get_property_by_offset(fdt, offset, &len))) {
+			offset = -FDT_ERR_INTERNAL;
+			break;
+		}
+		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+				   "phandle", strlen("phandle")))
+			php = (const fdt32_t *)prop->data;
+
+		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+				   "linux,phandle", strlen("linux,phandle")))
+			php = (const fdt32_t *)prop->data;
+
+		if (php)
+			return fdt32_to_cpu(*php);
 	}
 
-	return fdt32_to_cpu(*php);
+	return 0;
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux