[Skiboot] [PATCH v8 02/10] dt: Add phandle fixup helpers

Stewart Smith stewart at linux.vnet.ibm.com
Fri Apr 7 09:31:38 AEST 2017


Madhavan Srinivasan <maddy at linux.vnet.ibm.com> writes:
> Patch to add a phandle fixup function for a new
> incoming subtree. When attaching a "subtree" to
> main dt, subtree could have "property" referring
> different nodes or multiple nodes via phandle as
> "labels". For this reason, new subtree will have
> "phandle" already assigned to some of it's nodes.
> If this new subtree is attached to main dt without
> phandle fixup, could lead to duplicate phandle errors.
>
> Patch also carries other helper routines for phandle
> fixup function.
>
> Signed-off-by: Anju T Sudhakar <anju at linux.vnet.ibm.com>
> Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
> ---
>  core/device.c    | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/device.h |  21 +++++++++++
>  2 files changed, 131 insertions(+)

Please add some unit tests for this new functionality in
core/test/run-dt-insert-subtree.c or similar, I'd like to see this code
regularly run under valgrind and with a variety of inputs.

>
> diff --git a/core/device.c b/core/device.c
> index 170e0ee7bbb5..33cbf8dbc13e 100644
> --- a/core/device.c
> +++ b/core/device.c
> @@ -849,6 +849,116 @@ void dt_expand(const void *fdt)
>  		abort();
>  }
>
> +/*
> + * Helper to free malloced dt_fixup _list_ variables
> + */
> +void dt_fixup_list_free(struct dt_fixup_p *parent)
> +{
> +	struct dt_fixup_c *cptr, *ccptr;
> +
> +	list_for_each(&parent->children, cptr, list) {
> +		list_for_each(&cptr->children, ccptr, list)
> +			free(ccptr);
> +		free(cptr);
> +	}
> +}
> +
> +/*
> + * Function to capture the "property" and the node
> + * that needs phandle fixup via _list_
> + *
> + * Function first parser the new subtree for a "property"
> + * and adds to a _list_. If the "property" supports more than
> + * one "phandle" value, then the _list_ becomes 2D. i.e,
> + * say the "property" here is "events",
> + *
> + * <parent>
> + *    |
> + * <events <1> > - <node 1> - <node 2> -- <node n>
> + *    |
> + * <events <2> > - <node 1> - <node 2> -- <node n>
> + *    |
> + * <events <n> > - <node 1> - <node 2> -- <node n>
> + *
> + * < node *>  have events "property" and needs an
> + * update after phandle change.
> + */
> +int dt_fixup_populate_llist(struct dt_node *lr_node, struct dt_fixup_p *parent, const char *name)
> +{
> +	u32 ev_value;
> +	struct dt_fixup_c *cptr, *ccptr;
> +	bool flag = true;
> +	struct dt_node *node;
> +
> +	/* Initialize */
> +	list_head_init(&parent->children);
> +
> +	/* Loop through each node in the subtree */
> +	dt_for_each_node(lr_node, node) {
> +		/* Look for the given "property */
> +		if (dt_find_property(node, name)) {
> +			/* extract the "phandle" value */
> +			ev_value = dt_prop_get_u32(node, name);
> +			list_for_each(&parent->children, cptr, list) {
> +				if (cptr->events == ev_value) {
> +					flag = false;
> +					/* Grow the list horizontally */
> +					ccptr = malloc(sizeof(struct dt_fixup_c));
> +					if (!ccptr)
> +						return -ENOMEM;
> +
> +					/* capture information */
> +					ccptr->node = node;
> +					ccptr->name = name;
> +					list_add(&cptr->children, &ccptr->list);
> +					break;
> +				}
> +			}
> +			if (flag){
> +				cptr = malloc(sizeof(struct dt_fixup_c));
> +				if (!cptr)
> +					return -ENOMEM;
> +
> +				cptr->events = ev_value;
> +				cptr->node = node;
> +
> +				/* Grow the list vertically */
> +				list_add(&parent->children, &cptr->list);
> +				list_head_init(&cptr->children);
> +				ccptr = malloc(sizeof(struct dt_fixup_c));
> +				if (!ccptr)
> +					return -ENOMEM;
> +
> +				ccptr->node = node;
> +				ccptr->name = name;
> +				list_add(&cptr->children, &ccptr->list);
> +			}
> +			flag = true;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +int dt_fixup_phandle(struct dt_node *dev, struct dt_fixup_p *parent)
> +{
> +	struct dt_node *node;
> +	struct dt_property *prop;
> +	struct dt_fixup_c *cptr, *ccptr;
> +
> +	list_for_each(&parent->children, cptr, list) {
> +		node = dt_find_by_phandle(dev, cptr->events);
> +		if (node->phandle == cptr->events) {
> +			node->phandle = increment_return_last_phandle();
> +			list_for_each(&cptr->children, ccptr, list) {
> +				prop = __dt_find_property(ccptr->node, "events");
> +				memcpy(prop->prop, &node->phandle,
> prop->len);

This makes the code look specific to nodes with "events" properties?
Why? For something sitting in core/device.c, it should be generic.

-- 
Stewart Smith
OPAL Architect, IBM.



More information about the Skiboot mailing list