Message ID | 20200311221118.4579-6-trini@konsulko.com |
---|---|
State | Accepted |
Commit | 6e916dfd9da1648edce687affed682115cb1e7d6 |
Headers | show |
Series | [PATCHv2,1/8] spl: Kconfig: Escape '$(ARCH)' in LDSCRIPT entries | expand |
On Wed, Mar 11, 2020 at 5:11 PM Tom Rini <trini at konsulko.com> wrote: > > From: Rob Herring <robh at kernel.org> > > 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 That's 100s of commits behind master. Any reason why (IIRC, you revert the unaligned handling change)? In particular, there's a fix for GCC 10 and clang with commit: 0e9225eb0dfe Remove redundant YYLOC global declaration Only just now pointed out to me for updating the kernel copy. Though I guess this could be handled with '-fcommon' instead. Rob > > [From Linux Kernel commit 50aafd60898a8b3edf2f60e014a8288da3b2e5e3] > Signed-off-by: Rob Herring <robh at kernel.org> > > [For applying to U-Boot] > Signed-off-by: Tom Rini <trini at konsulko.com> > --- > scripts/dtc/checks.c | 186 +++++++++++++++++++++++++++++++++++++- > scripts/dtc/dtc-parser.y | 22 ++--- > scripts/dtc/livetree.c | 12 ++- > scripts/dtc/version_gen.h | 2 +- > 4 files changed, 206 insertions(+), 16 deletions(-) > > diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c > index 40879677c8c3..c35aa6f88639 100644 > --- a/scripts/dtc/checks.c > +++ b/scripts/dtc/checks.c > @@ -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); > > @@ -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) > @@ -1030,6 +1035,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) > @@ -1370,6 +1405,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, > @@ -1404,6 +1585,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, > > @@ -1430,6 +1612,8 @@ static struct check *check_table[] = { > > &alias_paths, > > + &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint, > + > &always_fail, > }; > > diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y > index 66ff7f7d8eb7..011a5b25539a 100644 > --- a/scripts/dtc/dtc-parser.y > +++ b/scripts/dtc/dtc-parser.y > @@ -191,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); > } > diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c > index 81b6c484542d..6e4c367f54b3 100644 > --- a/scripts/dtc/livetree.c > +++ b/scripts/dtc/livetree.c > @@ -238,10 +238,16 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) > struct data d = empty_data; > char *name; > > - d = data_add_marker(d, REF_PHANDLE, ref); > - d = data_append_integer(d, 0xffffffff, 32); > + if (ref[0] == '/') { > + d = data_append_data(d, ref, strlen(ref) + 1); > > - p = build_property("target", d); > + p = build_property("target-path", d); > + } else { > + d = data_add_marker(d, REF_PHANDLE, ref); > + d = data_append_integer(d, 0xffffffff, 32); > + > + p = build_property("target", d); > + } > > xasprintf(&name, "fragment@%u", > next_orphan_fragment++); > diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h > index ad87849e333b..b00f14ff7a17 100644 > --- a/scripts/dtc/version_gen.h > +++ b/scripts/dtc/version_gen.h > @@ -1 +1 @@ > -#define DTC_VERSION "DTC 1.4.6-gaadd0b65" > +#define DTC_VERSION "DTC 1.4.6-g84e414b0" > -- > 2.17.1 >
On Fri, Mar 13, 2020 at 03:01:05PM -0500, Rob Herring wrote: > On Wed, Mar 11, 2020 at 5:11 PM Tom Rini <trini at konsulko.com> wrote: > > > > From: Rob Herring <robh at kernel.org> > > > > 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 > > That's 100s of commits behind master. Any reason why (IIRC, you revert > the unaligned handling change)? In particular, there's a fix for GCC > 10 and clang with commit: > > 0e9225eb0dfe Remove redundant YYLOC global declaration > > Only just now pointed out to me for updating the kernel copy. Though I > guess this could be handled with '-fcommon' instead. I'm (slowly) getting all of the U-Boot Kbuild/Kconfig (and so, dtc) infrastructure in-line with Linux again, and then try and keep it up to date.
On Wed, Mar 11, 2020 at 06:11:16PM -0400, Tom Rini wrote: > From: Rob Herring <robh at kernel.org> > > 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 > > [From Linux Kernel commit 50aafd60898a8b3edf2f60e014a8288da3b2e5e3] > Signed-off-by: Rob Herring <robh at kernel.org> > > [For applying to U-Boot] > Signed-off-by: Tom Rini <trini at konsulko.com> Applied to u-boot/next, thanks!
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 40879677c8c3..c35aa6f88639 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -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); @@ -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) @@ -1030,6 +1035,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) @@ -1370,6 +1405,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, @@ -1404,6 +1585,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, @@ -1430,6 +1612,8 @@ static struct check *check_table[] = { &alias_paths, + &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint, + &always_fail, }; diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 66ff7f7d8eb7..011a5b25539a 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -191,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); } diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 81b6c484542d..6e4c367f54b3 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -238,10 +238,16 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) struct data d = empty_data; char *name; - d = data_add_marker(d, REF_PHANDLE, ref); - d = data_append_integer(d, 0xffffffff, 32); + if (ref[0] == '/') { + d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target", d); + p = build_property("target-path", d); + } else { + d = data_add_marker(d, REF_PHANDLE, ref); + d = data_append_integer(d, 0xffffffff, 32); + + p = build_property("target", d); + } xasprintf(&name, "fragment@%u", next_orphan_fragment++); diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index ad87849e333b..b00f14ff7a17 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.6-gaadd0b65" +#define DTC_VERSION "DTC 1.4.6-g84e414b0"