Thread (1 message) 1 message, 1 author, 2011-11-21

[RFC 3/8] of: create of_phandle_args to simplify return of phandle parsing data

From: Shawn Guo <hidden>
Date: 2011-11-21 15:38:39
Also in: linux-devicetree, lkml

On Tue, Nov 08, 2011 at 06:19:38PM -0700, Grant Likely wrote:
[...]
quoted hunk
 /**
- * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * of_parse_phandle_with_args - Find a node pointed by phandle in a list
  * @np:		pointer to a device tree node containing a list
  * @list_name:	property name that contains a list
  * @cells_name:	property name that specifies phandles' arguments count
  * @index:	index of a phandle to parse out
- * @out_node:	optional pointer to device_node struct pointer (will be filled)
- * @out_args:	optional pointer to arguments pointer (will be filled)
+ * @out_args:	optional pointer to output arguments structure (will be filled)
  *
  * This function is useful to parse lists of phandles and their arguments.
- * Returns 0 on success and fills out_node and out_args, on error returns
- * appropriate errno value.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
  *
  * Example:
  *
@@ -851,94 +850,105 @@ EXPORT_SYMBOL(of_parse_phandle);
  * }
  *
  * To get a device_node of the `node2' node you may call this:
- * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ * of_parse_phandle_with_args(node3, "list", "#list-cells", 2, &args);
Not introduced by this patch, but if I read the code correctly,
the fourth parameter should be 1?
  */
-int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
+int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
 				const char *cells_name, int index,
-				struct device_node **out_node,
-				const void **out_args)
+				struct of_phandle_args *out_args)
 {
 	int ret = -EINVAL;
-	const __be32 *list;
-	const __be32 *list_end;
-	int size;
-	int cur_index = 0;
+	const __be32 *list, *list_end;
+	int size, cur_index = 0;
+	uint32_t count = 0;
 	struct device_node *node = NULL;
-	const void *args = NULL;
+	phandle phandle;
 
+	/* Retrieve the phandle list property */
 	list = of_get_property(np, list_name, &size);
-	if (!list) {
-		ret = -ENOENT;
+	if (!list)
 		goto err0;
-	}
 	list_end = list + size / sizeof(*list);
 
+	/*
+	 * Loop over all the entries in the list, parsing the #cells property
+	 * for each one to determine how long each argument list is
+	 */
 	while (list < list_end) {
-		const __be32 *cells;
-		phandle phandle;
+		count = 0;
 
+		/*
+		 * If phandle is null, then it is an empty entry with no args,
+		 * skip forward to the next entry
+		 */
 		phandle = be32_to_cpup(list++);
-		args = list;
-
-		/* one cell hole in the list = <>; */
-		if (!phandle)
-			goto next;
-
-		node = of_find_node_by_phandle(phandle);
-		if (!node) {
-			pr_debug("%s: could not find phandle\n",
-				 np->full_name);
-			goto err0;
-		}
+		if (phandle) {
+			/*
+			 * Find the provider node and parse the #*-cells
+			 * property to determine how long the arguements are
+			 */
+			node = of_find_node_by_phandle(phandle);
+			if (!node) {
+				pr_debug("%s: could not find phandle\n",
+					 np->full_name);
+				ret = -EINVAL;
+				goto err0;
+			}
+			if (of_property_read_u32(node, cells_name, &count)) {
+				pr_debug("%s: could not get %s for %s\n",
+					 np->full_name, cells_name,
+					 node->full_name);
+				ret = -EINVAL;
+				goto err1;
+			}
 
-		cells = of_get_property(node, cells_name, &size);
-		if (!cells || size != sizeof(*cells)) {
-			pr_debug("%s: could not get %s for %s\n",
-				 np->full_name, cells_name, node->full_name);
-			goto err1;
+			/*
+			 * Make sure that the arguments actually fit in the
+			 * remaining property data length
+			 */
+			if (list + count > list_end) {
+				pr_debug("%s: insufficient arguments length\n",
+					 np->full_name);
+				goto err1;
+			}
 		}
 
-		list += be32_to_cpup(cells);
-		if (list > list_end) {
-			pr_debug("%s: insufficient arguments length\n",
-				 np->full_name);
-			goto err1;
-		}
-next:
-		if (cur_index == index)
+		/*
+		 * All of the error cases in the loop bail out to the err
+		 * labels, so at this point, the parsing was successful, but
+		 * it might be an empty entry
+		 */
+		if (cur_index == index) {
+			ret = phandle ? 0 : -ENOENT;
We have some return code here ...
 			break;
+		}
 
 		of_node_put(node);
 		node = NULL;
-		args = NULL;
+		list += count;
 		cur_index++;
 	}
 
-	if (!node) {
-		/*
-		 * args w/o node indicates that the loop above has stopped at
-		 * the 'hole' cell. Report this differently.
-		 */
-		if (args)
-			ret = -EEXIST;
-		else
-			ret = -ENOENT;
+	if (!node)
 		goto err0;
-	}
-
-	if (out_node)
-		*out_node = node;
-	if (out_args)
-		*out_args = args;
 
+	if (out_args) {
+		int i;
+		if (WARN_ON(count > MAX_PHANDLE_ARGS))
+			count = MAX_PHANDLE_ARGS;
+		out_args->np = node;
+		out_args->args_count = count;
+		for (i = 0; i < count; i++)
+			out_args->args[i] = be32_to_cpup(list++);
+	}
 	return 0;
... should this be "return ret"?
-err1:
+
+ err1:
 	of_node_put(node);
-err0:
+ err0:
 	pr_debug("%s failed with status %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL(of_parse_phandles_with_args);
+EXPORT_SYMBOL(of_parse_phandle_with_args);
 
-- 
Regards,
Shawn
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help