From patchwork Tue May 8 13:51:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 135158 Delivered-To: patch@linaro.org Received: by 10.46.151.6 with SMTP id r6csp4414850lji; Tue, 8 May 2018 06:52:12 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoP51Ye7qvUgBZEMaDFJgWAuXvKNmGK5/HBC6uTQfppi1QV22Yim4dADkEHn9rhGiAwpwv3 X-Received: by 2002:a17:902:229:: with SMTP id 38-v6mr16015662plc.384.1525787532068; Tue, 08 May 2018 06:52:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525787532; cv=none; d=google.com; s=arc-20160816; b=qFfTMZoxDO1m6kYfgtQG3Ma3f+7soMDtnIGmbhesqAE3btmNVY6LtCbUR2cMOi2XqS kIJ9/MLRPjjorcWlV3qqLlrnq6VJMbRjO0obxBn19Fr8neNaChj8aJ4+Tp2FbTweXfQ6 suv0ZZYzc4d6RJH3Iee+U+D38Z2545YPmL+iAtoC6iujHTTSmWO9cAsK35R8Xy6EPdmz KyGoOuH96ZusUol0uEdtlkoAV5UTqet1fYtcMkHI81oZ4NL1ZYDIMJNRFcMkW+i3xVWE 5m1AEUSrojhDUFJRCNZtUCyEAGCX7jX73kIYdcU7zr/6niPphobq1TF+tFjqSUqClAXu CEmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=WxR9Blc7PTsbRyL8MGWk0vX0+fvhEs6TMBX3N8lS8A0=; b=cOJS0+Iu7+RIsSo07/B1sBdlVvHFcF6SEAsCrZa+yTbMzHlcUn3H/tGX+yqgKc0Juw 2mdCN/RLg1rE1ilfKq52ulHAO6NBDMdle2YvFrTI6NOXPAzYg4Q2vyIZhKo8a6oqnUnq 6ByeF6Ako4kpC419y1nneQT434RPLuM/3p+wB5P+D830CLilfqfo5mFry631Y44nPV2l pINNT+Np3dq3MgTXPyTWxk4Srs68izgyq8/KlQO6dZHlSjHQJ3IXpKB3hgRfSTguPS89 U8bI2jsU4iX72qeSuKZInVHSVqqs0CgoVm4PX/9+THEXo62ahuOC9SZ27Bj6XLexRS6g 8nuw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u3-v6si24906963plb.593.2018.05.08.06.52.11; Tue, 08 May 2018 06:52:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755282AbeEHNv4 (ORCPT + 29 others); Tue, 8 May 2018 09:51:56 -0400 Received: from mail-oi0-f65.google.com ([209.85.218.65]:39743 "EHLO mail-oi0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755183AbeEHNvx (ORCPT ); Tue, 8 May 2018 09:51:53 -0400 Received: by mail-oi0-f65.google.com with SMTP id n65-v6so28385708oig.6; Tue, 08 May 2018 06:51:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=WxR9Blc7PTsbRyL8MGWk0vX0+fvhEs6TMBX3N8lS8A0=; b=TViCCb+RKg0paz/elkt//jWfp5LEjwB0UKta0Br9K5zRYWnCOLiHpIyEngMaSsF6ga Go9BHrZ1umM71FFn+DUGu1QRZjZY2tiawdKJAMS7GFG2WWsx/wgVHb731mdva/3abNx/ 8wCribFE/QpRX6kOiL0vXuJIwiaJnqkDHZ4KWYIBU+QehYDo2wbtAQp/Sns7AfMK3NNV AQWneEeOb45kuBeSzeeTAEY+Xf1sDD7cI0ztyf6K/ddqvR875yXDa/+nP9/hqL9LgAcn der2MY4Cm8P6h322njXWhT6DLO/jkpeTMn/8mJ9JglRzpdAHqJRvM/IlatKjfPzf0VLb Y8GA== X-Gm-Message-State: ALQs6tCdV7BRn6E1MZ5MHIuqAjEYRJECKXBk+hI4+y8JdOZnwKB+rGmm 2X53wkeZLyRRPH700ngcpdjDIDcbHA== X-Received: by 2002:aca:d447:: with SMTP id l68-v6mr27398112oig.102.1525787512059; Tue, 08 May 2018 06:51:52 -0700 (PDT) Received: from xps15.herring.priv (216-188-254-6.dyn.grandenetworks.net. [216.188.254.6]) by smtp.googlemail.com with ESMTPSA id n19-v6sm16735351otd.57.2018.05.08.06.51.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 May 2018 06:51:51 -0700 (PDT) From: Rob Herring To: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Frank Rowand , Maxime Ripard , Geert Uytterhoeven Subject: [PATCH 1/2] scripts/dtc: Update to upstream version v1.4.6-21-g84e414b0b5bc Date: Tue, 8 May 2018 08:51:49 -0500 Message-Id: <20180508135150.27762-1-robh@kernel.org> X-Mailer: git-send-email 2.17.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.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 Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 204 +++++++++++++++++++++++++++++++++++++- scripts/dtc/dtc-lexer.l | 7 ++ scripts/dtc/dtc-parser.y | 39 ++++++-- scripts/dtc/dtc.h | 4 + scripts/dtc/livetree.c | 26 ++++- scripts/dtc/version_gen.h | 2 +- 6 files changed, 263 insertions(+), 19 deletions(-) -- 2.17.0 diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index c07ba4da9e36..a2cc1036c915 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) @@ -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); } } } @@ -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 */ @@ -787,10 +804,9 @@ static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node * FAIL(c, dti, node, "incorrect #size-cells for PCI bridge"); prop = get_property(node, "bus-range"); - if (!prop) { - FAIL(c, dti, node, "missing bus-range for PCI bridge"); + if (!prop) return; - } + if (prop->val.len != (sizeof(cell_t) * 2)) { FAIL_PROP(c, dti, node, prop, "value must be 2 cells"); return; @@ -1018,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) @@ -1358,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, @@ -1367,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, @@ -1391,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, @@ -1417,6 +1611,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-lexer.l b/scripts/dtc/dtc-lexer.l index fd825ebba69c..615b7ec6588f 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/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("\n"); + BEGIN(PROPNODENAME); + return DT_OMIT_NO_REF; + } + <*>{LABEL}: { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 44af170abfea..011a5b25539a 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/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 DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL @@ -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 ($-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 ($-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); } @@ -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/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 3b18a42b866e..6d667701ab6a 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/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/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 57b7db2ed153..6e4c367f54b3 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/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; @@ -224,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"