Re: [PATCH v2 1/2] dtc: add ability to make nodes conditional on them being referenced

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



On Thu, May 03, 2018 at 10:27:26PM +0200, Maxime Ripard wrote:
> A number of platforms have a need to reduce the number of DT nodes,
> mostly because of two similar constraints: the size of the DT blob, and
> the time it takes to parse it.
> 
> As the DT is used in more and more SoCs, and by more projects, some
> constraints start to appear in bootloaders running from SRAM with an
> order of magnitude of 10kB. A typical DT is in the same order of
> magnitude, so any effort to reduce the blob size is welcome in such an
> environment.
> 
> Some platforms also want to reach very fast boot time, and the time it
> takes to parse a typical DT starts to be noticeable.
> 
> Both of these issues can be mitigated by reducing the number of nodes in
> the DT. The biggest provider of nodes is usually the pin controller and
> its subnodes, usually one for each valid pin configuration in a given
> SoC.
> 
> Obviously, a single, fixed, set of these nodes will be used by a given
> board, so we can introduce a node property that will tell the DT
> compiler to drop the nodes when they are not referenced in the tree, and
> as such wouldn't be useful in the targetted system.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@xxxxxxxxxxx>

Applied, thanks.

> 
> ---
> Changes from v1:
>   - Rename the property from delete-if-unreferenced to omit-if-no-ref
>   - Change the various variables in the code to reflect this
>   - Added support to set the property on a label instead of a full node
>   - Also take into account the reference by path, and not only by
>     phandle
>   - Prune the unused nodes in a fixup pass, and not during the tree
>     flattening that allows to have the same behaviour when having an
>     output to a format other than dtb or asm
>   - Rebased on current master
> ---
>  checks.c     | 13 +++++++++++++
>  dtc-lexer.l  |  7 +++++++
>  dtc-parser.y | 17 +++++++++++++++++
>  dtc.h        |  4 ++++
>  livetree.c   | 14 ++++++++++++++
>  5 files changed, 55 insertions(+)
> 
> diff --git a/checks.c b/checks.c
> index dca45aca73d7..a2cc1036c915 100644
> --- a/checks.c
> +++ b/checks.c
> @@ -584,6 +584,8 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
>  
>  			phandle = get_node_phandle(dt, refnode);
>  			*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
> +
> +			reference_node(refnode);
>  		}
>  	}
>  }
> @@ -614,11 +616,21 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
>  			path = refnode->fullpath;
>  			prop->val = data_insert_at_marker(prop->val, m, path,
>  							  strlen(path) + 1);
> +
> +			reference_node(refnode);
>  		}
>  	}
>  }
>  ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
>  
> +static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
> +				    struct node *node)
> +{
> +	if (node->omit_if_unused && !node->is_referenced)
> +		delete_node(node);
> +}
> +ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
> +
>  /*
>   * Semantic checks
>   */
> @@ -1547,6 +1559,7 @@ static struct check *check_table[] = {
>  
>  	&explicit_phandles,
>  	&phandle_references, &path_references,
> +	&omit_unused_nodes,
>  
>  	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
>  	&device_type_is_string, &model_is_string, &status_is_string,
> diff --git a/dtc-lexer.l b/dtc-lexer.l
> index fd825ebba69c..615b7ec6588f 100644
> --- a/dtc-lexer.l
> +++ b/dtc-lexer.l
> @@ -153,6 +153,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
>  			return DT_DEL_NODE;
>  		}
>  
> +<*>"/omit-if-no-ref/"	{
> +			DPRINT("Keyword: /omit-if-no-ref/\n");
> +			DPRINT("<PROPNODENAME>\n");
> +			BEGIN(PROPNODENAME);
> +			return DT_OMIT_NO_REF;
> +		}
> +
>  <*>{LABEL}:	{
>  			DPRINT("Label: %s\n", yytext);
>  			yylval.labelref = xstrdup(yytext);
> diff --git a/dtc-parser.y b/dtc-parser.y
> index 25e92d64305c..011a5b25539a 100644
> --- a/dtc-parser.y
> +++ b/dtc-parser.y
> @@ -63,6 +63,7 @@ extern bool treesource_error;
>  %token DT_BITS
>  %token DT_DEL_PROP
>  %token DT_DEL_NODE
> +%token DT_OMIT_NO_REF
>  %token <propnodename> DT_PROPNODENAME
>  %token <integer> DT_LITERAL
>  %token <integer> DT_CHAR_LITERAL
> @@ -217,6 +218,18 @@ devicetree:
>  				ERROR(&@3, "Label or path %s not found", $3);
>  
>  
> +			$$ = $1;
> +		}
> +	| devicetree DT_OMIT_NO_REF DT_REF ';'
> +		{
> +			struct node *target = get_node_by_ref($1, $3);
> +
> +			if (target)
> +				omit_node_if_unused(target);
> +			else
> +				ERROR(&@3, "Label or path %s not found", $3);
> +
> +
>  			$$ = $1;
>  		}
>  	;
> @@ -523,6 +536,10 @@ subnode:
>  		{
>  			$$ = name_node(build_node_delete(), $2);
>  		}
> +	| DT_OMIT_NO_REF subnode
> +		{
> +			$$ = omit_node_if_unused($2);
> +		}
>  	| DT_LABEL subnode
>  		{
>  			add_label(&$2->labels, $1);
> diff --git a/dtc.h b/dtc.h
> index 3b18a42b866e..6d667701ab6a 100644
> --- a/dtc.h
> +++ b/dtc.h
> @@ -168,6 +168,8 @@ struct node {
>  
>  	struct label *labels;
>  	const struct bus_type *bus;
> +
> +	bool omit_if_unused, is_referenced;
>  };
>  
>  #define for_each_label_withdel(l0, l) \
> @@ -202,6 +204,8 @@ struct property *reverse_properties(struct property *first);
>  struct node *build_node(struct property *proplist, struct node *children);
>  struct node *build_node_delete(void);
>  struct node *name_node(struct node *node, char *name);
> +struct node *omit_node_if_unused(struct node *node);
> +struct node *reference_node(struct node *node);
>  struct node *chain_node(struct node *first, struct node *list);
>  struct node *merge_nodes(struct node *old_node, struct node *new_node);
>  struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
> diff --git a/livetree.c b/livetree.c
> index f691c9b5c935..6e4c367f54b3 100644
> --- a/livetree.c
> +++ b/livetree.c
> @@ -134,6 +134,20 @@ struct node *name_node(struct node *node, char *name)
>  	return node;
>  }
>  
> +struct node *omit_node_if_unused(struct node *node)
> +{
> +	node->omit_if_unused = 1;
> +
> +	return node;
> +}
> +
> +struct node *reference_node(struct node *node)
> +{
> +	node->is_referenced = 1;
> +
> +	return node;
> +}
> +
>  struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  {
>  	struct property *new_prop, *old_prop;

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


[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