Skip to content

Commit

Permalink
scripts/dtc: Update to upstream version v1.4.6-21-g84e414b0b5bc
Browse files Browse the repository at this point in the history
This adds the following commits from upstream:

84e414b0b5bc tests: Add a test case for the omit-if-no-ref keyword
4038fd90056e dtc: add ability to make nodes conditional on them being referenced
e1f139ea4900 checks: drop warning for missing PCI bridge bus-range
f4eba68d89ee checks: Print duplicate node name instead of parent name
46df1fb1b211 .travis.yml: Run valgrind checks via Travis
14a3002a1aee tests: Update valgrind suppressions for sw_tree1
02c5fe9debc0 tests: Remove valgrind error from tests/get_path
df536831d02c checks: add graph binding checks
2347c96edcbe checks: add a check for duplicate unit-addresses of child nodes
8f1b35f88395 Correct overlay syntactic sugar for generating target-path fragments
afbddcd418fb Suppress warnings on overlay fragments
119e27300359 Improve tests for dtc overlay generation

Signed-off-by: Rob Herring <[email protected]>
  • Loading branch information
robherring committed May 15, 2018
1 parent 9601000 commit 50aafd6
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 16 deletions.
199 changes: 198 additions & 1 deletion scripts/dtc/checks.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2;
child2 = child2->next_sibling)
if (streq(child->name, child2->name))
FAIL(c, dti, node, "Duplicate node name");
FAIL(c, dti, child2, "Duplicate node name");
}
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);

Expand Down Expand Up @@ -317,6 +317,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg");

if (get_subnode(node, "__overlay__")) {
/* HACK: Overlay fragments are a special case */
return;
}

if (!prop) {
prop = get_property(node, "ranges");
if (prop && !prop->val.len)
Expand Down Expand Up @@ -579,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);
}
}
}
Expand Down Expand Up @@ -609,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
*/
Expand Down Expand Up @@ -1017,6 +1034,36 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d
}
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);

static void check_unique_unit_address(struct check *c, struct dt_info *dti,
struct node *node)
{
struct node *childa;

if (node->addr_cells < 0 || node->size_cells < 0)
return;

if (!node->children)
return;

for_each_child(node, childa) {
struct node *childb;
const char *addr_a = get_unitname(childa);

if (!strlen(addr_a))
continue;

for_each_child(node, childb) {
const char *addr_b = get_unitname(childb);
if (childa == childb)
break;

if (streq(addr_a, addr_b))
FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
}
}
}
WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);

static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct dt_info *dti,
struct node *node)
Expand Down Expand Up @@ -1357,6 +1404,152 @@ static void check_interrupts_property(struct check *c,
}
WARNING(interrupts_property, check_interrupts_property, &phandle_references);

static const struct bus_type graph_port_bus = {
.name = "graph-port",
};

static const struct bus_type graph_ports_bus = {
.name = "graph-ports",
};

static void check_graph_nodes(struct check *c, struct dt_info *dti,
struct node *node)
{
struct node *child;

for_each_child(node, child) {
if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
get_property(child, "remote-endpoint")))
continue;

node->bus = &graph_port_bus;

/* The parent of 'port' nodes can be either 'ports' or a device */
if (!node->parent->bus &&
(streq(node->parent->name, "ports") || get_property(node, "reg")))
node->parent->bus = &graph_ports_bus;

break;
}

}
WARNING(graph_nodes, check_graph_nodes, NULL);

static void check_graph_child_address(struct check *c, struct dt_info *dti,
struct node *node)
{
int cnt = 0;
struct node *child;

if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
return;

for_each_child(node, child) {
struct property *prop = get_property(child, "reg");

/* No error if we have any non-zero unit address */
if (prop && propval_cell(prop) != 0)
return;

cnt++;
}

if (cnt == 1 && node->addr_cells != -1)
FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
node->children->name);
}
WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);

static void check_graph_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
char unit_addr[9];
const char *unitname = get_unitname(node);
struct property *prop;

prop = get_property(node, "reg");
if (!prop || !unitname)
return;

if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
FAIL(c, dti, node, "graph node malformed 'reg' property");
return;
}

snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
if (!streq(unitname, unit_addr))
FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
unit_addr);

if (node->parent->addr_cells != 1)
FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
"graph node '#address-cells' is %d, must be 1",
node->parent->addr_cells);
if (node->parent->size_cells != 0)
FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
"graph node '#size-cells' is %d, must be 0",
node->parent->size_cells);
}

static void check_graph_port(struct check *c, struct dt_info *dti,
struct node *node)
{
if (node->bus != &graph_port_bus)
return;

if (!strprefixeq(node->name, node->basenamelen, "port"))
FAIL(c, dti, node, "graph port node name should be 'port'");

check_graph_reg(c, dti, node);
}
WARNING(graph_port, check_graph_port, NULL, &graph_nodes);

static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
int phandle;
struct node *node;
struct property *prop;

prop = get_property(endpoint, "remote-endpoint");
if (!prop)
return NULL;

phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
if (phandle == 0 || phandle == -1)
return NULL;

node = get_node_by_phandle(dti->dt, phandle);
if (!node)
FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");

return node;
}

static void check_graph_endpoint(struct check *c, struct dt_info *dti,
struct node *node)
{
struct node *remote_node;

if (!node->parent || node->parent->bus != &graph_port_bus)
return;

if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");

check_graph_reg(c, dti, node);

remote_node = get_remote_endpoint(c, dti, node);
if (!remote_node)
return;

if (get_remote_endpoint(c, dti, remote_node) != node)
FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
remote_node->fullpath);
}
WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);

static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
Expand All @@ -1366,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,
Expand All @@ -1390,6 +1584,7 @@ static struct check *check_table[] = {

&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
&unique_unit_address,
&obsolete_chosen_interrupt_controller,
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,

Expand All @@ -1416,6 +1611,8 @@ static struct check *check_table[] = {

&alias_paths,

&graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,

&always_fail,
};

Expand Down
7 changes: 7 additions & 0 deletions scripts/dtc/dtc-lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
39 changes: 28 additions & 11 deletions scripts/dtc/dtc-parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -190,18 +191,18 @@ devicetree:
}
| devicetree DT_REF nodedef
{
struct node *target = get_node_by_ref($1, $2);

if (target) {
merge_nodes(target, $3);
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves devicetree
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
add_orphan_node($1, $3, $2);
} else {
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves devicetree
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN)
add_orphan_node($1, $3, $2);
struct node *target = get_node_by_ref($1, $2);

if (target)
merge_nodes(target, $3);
else
ERROR(&@2, "Label or path %s not found", $2);
}
Expand All @@ -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;
}
;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions scripts/dtc/dtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 50aafd6

Please sign in to comment.