Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74e1fbb1 authored by Joerg Roedel's avatar Joerg Roedel Committed by Rob Herring
Browse files

of: Introduce struct of_phandle_iterator



This struct carrys all necessary information to iterate over
a list of phandles and extract the arguments. Add an
init-function for the iterator and make use of it in
__of_parse_phandle_with_args().

Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
parent 34b82026
Loading
Loading
Loading
Loading
+60 −39
Original line number Diff line number Diff line
@@ -1440,35 +1440,56 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
	printk("\n");
}

static int __of_parse_phandle_with_args(const struct device_node *np,
int of_phandle_iterator_init(struct of_phandle_iterator *it,
		const struct device_node *np,
		const char *list_name,
		const char *cells_name,
					int cell_count, int index,
					struct of_phandle_args *out_args)
		int cell_count)
{
	const __be32 *list, *list_end;
	int rc = 0, size, cur_index = 0;
	uint32_t count = 0;
	struct device_node *node = NULL;
	phandle phandle;
	const __be32 *list;
	int size;

	memset(it, 0, sizeof(*it));

	/* Retrieve the phandle list property */
	list = of_get_property(np, list_name, &size);
	if (!list)
		return -ENOENT;
	list_end = list + size / sizeof(*list);

	it->cells_name = cells_name;
	it->cell_count = cell_count;
	it->parent = np;
	it->list_end = list + size / sizeof(*list);
	it->phandle_end = list;
	it->cur = list;

	return 0;
}

static int __of_parse_phandle_with_args(const struct device_node *np,
					const char *list_name,
					const char *cells_name,
					int cell_count, int index,
					struct of_phandle_args *out_args)
{
	struct of_phandle_iterator it;
	int rc, cur_index = 0;

	rc = of_phandle_iterator_init(&it, np, list_name,
				      cells_name, cell_count);
	if (rc)
		return rc;

	/* Loop over the phandles until all the requested entry is found */
	while (list < list_end) {
	while (it.cur < it.list_end) {
		rc = -EINVAL;
		count = 0;
		it.cur_count = 0;

		/*
		 * If phandle is 0, then it is an empty entry with no
		 * arguments.  Skip forward to the next entry.
		 */
		phandle = be32_to_cpup(list++);
		if (phandle) {
		it.phandle = be32_to_cpup(it.cur++);
		if (it.phandle) {
			/*
			 * Find the provider node and parse the #*-cells
			 * property to determine the argument length.
@@ -1478,34 +1499,34 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
			 * except when we're going to return the found node
			 * below.
			 */
			if (cells_name || cur_index == index) {
				node = of_find_node_by_phandle(phandle);
				if (!node) {
			if (it.cells_name || cur_index == index) {
				it.node = of_find_node_by_phandle(it.phandle);
				if (!it.node) {
					pr_err("%s: could not find phandle\n",
						np->full_name);
						it.parent->full_name);
					goto err;
				}
			}

			if (cells_name) {
				if (of_property_read_u32(node, cells_name,
							 &count)) {
			if (it.cells_name) {
				if (of_property_read_u32(it.node, it.cells_name,
							 &it.cur_count)) {
					pr_err("%s: could not get %s for %s\n",
						np->full_name, cells_name,
						node->full_name);
						it.parent->full_name, it.cells_name,
						it.node->full_name);
					goto err;
				}
			} else {
				count = cell_count;
				it.cur_count = it.cell_count;
			}

			/*
			 * Make sure that the arguments actually fit in the
			 * remaining property data length
			 */
			if (list + count > list_end) {
			if (it.cur + it.cur_count > it.list_end) {
				pr_err("%s: arguments longer than property\n",
					 np->full_name);
					 it.parent->full_name);
				goto err;
			}
		}
@@ -1518,28 +1539,28 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
		 */
		rc = -ENOENT;
		if (cur_index == index) {
			if (!phandle)
			if (!it.phandle)
				goto err;

			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++);
				if (WARN_ON(it.cur_count > MAX_PHANDLE_ARGS))
					it.cur_count = MAX_PHANDLE_ARGS;
				out_args->np = it.node;
				out_args->args_count = it.cur_count;
				for (i = 0; i < it.cur_count; i++)
					out_args->args[i] = be32_to_cpup(it.cur++);
			} else {
				of_node_put(node);
				of_node_put(it.node);
			}

			/* Found it! return success */
			return 0;
		}

		of_node_put(node);
		node = NULL;
		list += count;
		of_node_put(it.node);
		it.node = NULL;
		it.cur += it.cur_count;
		cur_index++;
	}

@@ -1551,8 +1572,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
	 */
	rc = index < 0 ? cur_index : -ENOENT;
 err:
	if (node)
		of_node_put(node);
	if (it.node)
		of_node_put(it.node);
	return rc;
}

+33 −0
Original line number Diff line number Diff line
@@ -75,6 +75,23 @@ struct of_phandle_args {
	uint32_t args[MAX_PHANDLE_ARGS];
};

struct of_phandle_iterator {
	/* Common iterator information */
	const char *cells_name;
	int cell_count;
	const struct device_node *parent;

	/* List size information */
	const __be32 *list_end;
	const __be32 *phandle_end;

	/* Current position state */
	const __be32 *cur;
	uint32_t cur_count;
	phandle phandle;
	struct device_node *node;
};

struct of_reconfig_data {
	struct device_node	*dn;
	struct property		*prop;
@@ -334,6 +351,13 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
extern int of_count_phandle_with_args(const struct device_node *np,
	const char *list_name, const char *cells_name);

/* phandle iterator functions */
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
				    const struct device_node *np,
				    const char *list_name,
				    const char *cells_name,
				    int cell_count);

extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem);
extern int of_alias_get_highest_id(const char *stem);
@@ -608,6 +632,15 @@ static inline int of_count_phandle_with_args(struct device_node *np,
	return -ENOSYS;
}

static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
					   const struct device_node *np,
					   const char *list_name,
					   const char *cells_name,
					   int cell_count)
{
	return -ENOSYS;
}

static inline int of_alias_get_id(struct device_node *np, const char *stem)
{
	return -ENOSYS;