From patchwork Tue Oct 17 01:17:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826702 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="G9WBckLP"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHTt1BCmz9s82 for ; Tue, 17 Oct 2017 12:21:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755042AbdJQBVk (ORCPT ); Mon, 16 Oct 2017 21:21:40 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:45633 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756504AbdJQBSH (ORCPT ); Mon, 16 Oct 2017 21:18:07 -0400 Received: by mail-pg0-f68.google.com with SMTP id b192so130404pga.2; Mon, 16 Oct 2017 18:18:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xGX1MayxpM63wEZf7w71UO9fZ4ztrzisFW6akTVoV0w=; b=G9WBckLPIitDAb5lE5xgN3gAcp9694ntatpkMaKpoiaoY6iPm+DyJPwFZuU4pGw2y9 ATmO4PuvaeT9QNwqEMnAfSET1/2vBFdiMxDo48V4Nd9uxwRUjyxCGk+VXxly058tC8vm rHm4w+7Ogo56GjZetsS/4E7TCD7vLDHWt+jomzCP3NPN887hIiPZgOvHCRoDHWYXKDws rQP42WGYIh3IsdUIfAxHft4bed2v/byIhZO/9DRQSgFZsYBqPThEyYZmGUyyyzBR0HfG z6BEF+/AF0baZ3/R2DuyrN/7Sqf6Z/b6Hz+fFbvKeGcqWpAGm9wdnoR5zGpzRvEgnlbx qWVA== 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:in-reply-to :references; bh=xGX1MayxpM63wEZf7w71UO9fZ4ztrzisFW6akTVoV0w=; b=NWW8xCSzAyAhs9fxE0nDJnNUA7ZyKObETriNYNGQm37oW1nuq0WmJ3NUK2MAO0pzC2 r9EVptChJTW6uiJwLQKwy9HK0AXufFUCA3oZ6kFZO4y7YX/ee0kxSU0KOIGecEsO7Qni Wo1gjTreQ1QlMLZmC9yfeed4pF7p3kCTT5gJEZOzAU9MslcRN5dPMgG9/ZlDouG0Pi7P aAGuSPKU5UuedIJIQBZx8A/IJ8Im6EZVgtx4JLz8Ehe7P1KuWOb7iuJXDFTL/KtH/Q3s vg7Mwk2TBnBZovWy397SJ3mQUbK5pmCi0c9M3eKjqLCJwOC/RBtlVyTtR0VoA7Ylyxnh ZVcg== X-Gm-Message-State: AMCzsaVuOAgfOTytJCR7reWvXUJMYOwlMdX3R19xkPnJRFrAXHUgaRw9 O8XBjP40xu81A6u3i3kasQQ= X-Google-Smtp-Source: AOwi7QBapob7cd8UxPI2kl82jXiXwlqgTDHpMqcbKCiQoS3Z4pyjFk0ztSAirm6C14wHNZOyYTUtxQ== X-Received: by 10.84.240.3 with SMTP id y3mr9755471plk.22.1508203086461; Mon, 16 Oct 2017 18:18:06 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:05 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 01/12] of: overlay.c: Remove comments that state the obvious, to reduce clutter Date: Mon, 16 Oct 2017 18:17:43 -0700 Message-Id: <1508203074-26917-2-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand Follows recommendations in Documentation/process/coding-style.rst, section 8, Commenting. Some in function comments are promoted to function header comments. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 53 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 8ecfee31ab6d..26f63f10f4b0 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -143,7 +143,6 @@ static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, strcpy(new->value, target_path); strcpy(new->value + target_path_len, label_path); - /* mark the property as dynamic */ of_property_set_flag(new, OF_DYNAMIC); return new; @@ -157,23 +156,24 @@ static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, } +/* + * Some special properties are not updated (no error returned). + * Update of property in symbols node is not allowed. + */ static int of_overlay_apply_single_property(struct of_overlay *ov, struct device_node *target, struct property *prop, bool is_symbols_node) { struct property *propn = NULL, *tprop; - /* NOTE: Multiple changes of single properties not supported */ tprop = of_find_property(target, prop->name, NULL); - /* special properties are not meant to be updated (silent NOP) */ if (of_prop_cmp(prop->name, "name") == 0 || of_prop_cmp(prop->name, "phandle") == 0 || of_prop_cmp(prop->name, "linux,phandle") == 0) return 0; if (is_symbols_node) { - /* changing a property in __symbols__ node not allowed */ if (tprop) return -EINVAL; propn = dup_and_fixup_symbol_prop(ov, prop); @@ -184,14 +184,19 @@ static int of_overlay_apply_single_property(struct of_overlay *ov, if (propn == NULL) return -ENOMEM; - /* not found? add */ if (tprop == NULL) return of_changeset_add_property(&ov->cset, target, propn); - /* found? update */ return of_changeset_update_property(&ov->cset, target, propn); } +/* + * NOTE: Multiple mods of created nodes not supported. + * + * Return + * -ENOMEM if memory allocation fails + * -EINVAL if existing node has a phandle and overlay node has a phandle + */ static int of_overlay_apply_single_device_node(struct of_overlay *ov, struct device_node *target, struct device_node *child) { @@ -203,13 +208,11 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov, if (cname == NULL) return -ENOMEM; - /* NOTE: Multiple mods of created nodes not supported */ for_each_child_of_node(target, tchild) if (!of_node_cmp(cname, kbasename(tchild->full_name))) break; if (tchild != NULL) { - /* new overlay phandle value conflicts with existing value */ if (child->phandle) return -EINVAL; @@ -217,12 +220,10 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov, ret = of_overlay_apply_one(ov, tchild, child, 0); of_node_put(tchild); } else { - /* create empty tree as a target */ tchild = __of_node_dup(child, "%pOF/%s", target, cname); if (!tchild) return -ENOMEM; - /* point to parent */ tchild->parent = target; ret = of_changeset_attach_node(&ov->cset, tchild); @@ -243,6 +244,8 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov, * Note that the in case of an error the target node is left * in a inconsistent state. Error recovery should be performed * by using the changeset. + * + * Do not allow symbols node to have any children. */ static int of_overlay_apply_one(struct of_overlay *ov, struct device_node *target, const struct device_node *overlay, @@ -262,7 +265,6 @@ static int of_overlay_apply_one(struct of_overlay *ov, } } - /* do not allow symbols node to have any children */ if (is_symbols_node) return 0; @@ -292,7 +294,6 @@ static int of_overlay_apply(struct of_overlay *ov) { int i, err; - /* first we apply the overlays atomically */ for (i = 0; i < ov->count; i++) { struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; @@ -309,10 +310,10 @@ static int of_overlay_apply(struct of_overlay *ov) /* * Find the target node using a number of different strategies - * in order of preference + * in order of preference: * - * "target" property containing the phandle of the target - * "target-path" property containing the path of the target + * 1) "target" property containing the phandle of the target + * 2) "target-path" property containing the path of the target */ static struct device_node *find_target_node(struct device_node *info_node) { @@ -320,12 +321,10 @@ static struct device_node *find_target_node(struct device_node *info_node) u32 val; int ret; - /* first try to go by using the target as a phandle */ ret = of_property_read_u32(info_node, "target", &val); if (ret == 0) return of_find_node_by_phandle(val); - /* now try to locate by path */ ret = of_property_read_string(info_node, "target-path", &path); if (ret == 0) return of_find_node_by_path(path); @@ -390,7 +389,6 @@ static int of_build_overlay_info(struct of_overlay *ov, struct of_overlay_info *ovinfo; int cnt, err; - /* worst case; every child is a node */ cnt = 0; for_each_child_of_node(tree, node) cnt++; @@ -423,7 +421,6 @@ static int of_build_overlay_info(struct of_overlay *ov, cnt++; } - /* if nothing filled, return error */ if (cnt == 0) { kfree(ovinfo); return -ENODEV; @@ -479,7 +476,6 @@ int of_overlay_create(struct device_node *tree) struct of_overlay *ov; int err, id; - /* allocate the overlay structure */ ov = kzalloc(sizeof(*ov), GFP_KERNEL); if (ov == NULL) return -ENOMEM; @@ -498,7 +494,6 @@ int of_overlay_create(struct device_node *tree) } ov->id = id; - /* build the overlay info structures */ err = of_build_overlay_info(ov, tree); if (err) { pr_err("of_build_overlay_info() failed for tree@%pOF\n", @@ -513,18 +508,15 @@ int of_overlay_create(struct device_node *tree) goto err_free_idr; } - /* apply the overlay */ err = of_overlay_apply(ov); if (err) goto err_abort_trans; - /* apply the changeset */ err = __of_changeset_apply(&ov->cset); if (err) goto err_revert_overlay; - /* add to the tail of the overlay list */ list_add_tail(&ov->node, &ov_list); of_overlay_notify(ov, OF_OVERLAY_POST_APPLY); @@ -547,13 +539,15 @@ int of_overlay_create(struct device_node *tree) } EXPORT_SYMBOL_GPL(of_overlay_create); -/* check whether the given node, lies under the given tree */ +/* + * check whether the given node, lies under the given tree + * return 1 if under tree, else 0 + */ static int overlay_subtree_check(struct device_node *tree, struct device_node *dn) { struct device_node *child; - /* match? */ if (tree == dn) return 1; @@ -567,7 +561,10 @@ static int overlay_subtree_check(struct device_node *tree, return 0; } -/* check whether this overlay is the topmost */ +/* + * check whether this overlay is the topmost + * return 1 if topmost, else 0 + */ static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) { struct of_overlay *ovt; @@ -588,7 +585,6 @@ static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) } } - /* overlay is topmost */ return 1; } @@ -638,7 +634,6 @@ int of_overlay_destroy(int id) goto out; } - /* check whether the overlay is safe to remove */ if (!overlay_removal_is_ok(ov)) { err = -EBUSY; goto out; From patchwork Tue Oct 17 01:17:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826701 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cVH+iE9t"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHTS6s6Mz9s82 for ; Tue, 17 Oct 2017 12:21:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756579AbdJQBSL (ORCPT ); Mon, 16 Oct 2017 21:18:11 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:48722 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756547AbdJQBSI (ORCPT ); Mon, 16 Oct 2017 21:18:08 -0400 Received: by mail-pf0-f194.google.com with SMTP id b79so122903pfk.5; Mon, 16 Oct 2017 18:18:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=FUJ8EtUgq5AyxCIdRTn6azJboeUssCS50U3QKXPOx4I=; b=cVH+iE9tWJEvoCoW9BxIx6Yhb5PctjJ/t12WqDO6m2lW8TWkl30TJmJaFqQNw2segZ dz3LW6oioTRAR4tJdsgMWzH4f+WssF+b2vzThVI0hhgzwUi4FpxWA1ONnd8yUvM0xoEW GgJcT2IzUZiRSia/VzOqmBWEoXkrp+tG1HqL5I45xEAdFfL4WckTvVeJhFoTofSbNbbS NsbvyAoMw6iE1zZTiEiJ8W1QTngJhI4j3z9BpD6m8YrtMsNXAK0NRujAbwz/84NhrS91 dLUqaaIPITg0tZ9jlkyaNGNNTBiWsICuBBVckz8XM2Fnlt6UW2b3j+ZzLhZJwScvqglI 8dsQ== 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:in-reply-to :references; bh=FUJ8EtUgq5AyxCIdRTn6azJboeUssCS50U3QKXPOx4I=; b=Ado3ft00LzYgPljriPEe9a4Em2VNYsiLMvu6OIaUxmgL7sp/ZUHJ2rFH+bmZdUDKHb gUZBbjLggx3ZDbB6LmKCtJei9/g1svB9Jr1HJRK7gUx3+P2NySla7t11AGV2fN42oGII gPC9lE/oJtpd4jw6RQKrYKiRBaxYGCxGLgGE0isfhjGl2psRvRMru+6VrI2ci2AWorfu JLQvYD8TVfcyzZWtE1DZiw0sSdlB0vChbx4xunOQOpZlHM7emKlvL17RFKzk7I+2VB3P yLuVl1IdpjVRFl7Lc1yWJ2HDbjfVQSJgZp1kduPZ4UdX9LVdH7+1Qffv4nU+9TIJB4w1 ds7A== X-Gm-Message-State: AMCzsaW4lh/mMea7ianEJm0YxS7PvuN8NFtAO3e2SmS1EbWT0Hb+k/ky 51VhEoIk+p6ZhOWhkZCiYDE= X-Google-Smtp-Source: ABhQp+Ryp0zN985ibD5LrwjUzohixVbm6kg+YfDxodpM/+W05aSwJsHSrAAQ+LGiWDhajcgZ4lfwKw== X-Received: by 10.84.245.150 with SMTP id j22mr7210071pll.157.1508203087685; Mon, 16 Oct 2017 18:18:07 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:07 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 02/12] of: overlay.c: Convert comparisons to zero or NULL to logical expressions Date: Mon, 16 Oct 2017 18:17:44 -0700 Message-Id: <1508203074-26917-3-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand Use normal shorthand for comparing a variable to zero. For variable "XXX": convert (XXX == 0) to (!XXX) convert (XXX != 0) to (XXX) Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 26f63f10f4b0..8e0c7eb4858c 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -168,9 +168,9 @@ static int of_overlay_apply_single_property(struct of_overlay *ov, tprop = of_find_property(target, prop->name, NULL); - if (of_prop_cmp(prop->name, "name") == 0 || - of_prop_cmp(prop->name, "phandle") == 0 || - of_prop_cmp(prop->name, "linux,phandle") == 0) + if (!of_prop_cmp(prop->name, "name") || + !of_prop_cmp(prop->name, "phandle") || + !of_prop_cmp(prop->name, "linux,phandle")) return 0; if (is_symbols_node) { @@ -181,10 +181,10 @@ static int of_overlay_apply_single_property(struct of_overlay *ov, propn = __of_prop_dup(prop, GFP_KERNEL); } - if (propn == NULL) + if (!propn) return -ENOMEM; - if (tprop == NULL) + if (!tprop) return of_changeset_add_property(&ov->cset, target, propn); return of_changeset_update_property(&ov->cset, target, propn); @@ -205,14 +205,14 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov, int ret = 0; cname = kbasename(child->full_name); - if (cname == NULL) + if (!cname) return -ENOMEM; for_each_child_of_node(target, tchild) if (!of_node_cmp(cname, kbasename(tchild->full_name))) break; - if (tchild != NULL) { + if (tchild) { if (child->phandle) return -EINVAL; @@ -270,7 +270,7 @@ static int of_overlay_apply_one(struct of_overlay *ov, for_each_child_of_node(overlay, child) { ret = of_overlay_apply_single_device_node(ov, target, child); - if (ret != 0) { + if (ret) { pr_err("Failed to apply single node @%pOF/%s\n", target, child->name); of_node_put(child); @@ -299,7 +299,7 @@ static int of_overlay_apply(struct of_overlay *ov) err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay, ovinfo->is_symbols_node); - if (err != 0) { + if (err) { pr_err("apply failed '%pOF'\n", ovinfo->target); return err; } @@ -322,11 +322,11 @@ static struct device_node *find_target_node(struct device_node *info_node) int ret; ret = of_property_read_u32(info_node, "target", &val); - if (ret == 0) + if (!ret) return of_find_node_by_phandle(val); ret = of_property_read_string(info_node, "target-path", &path); - if (ret == 0) + if (!ret) return of_find_node_by_path(path); pr_err("Failed to find target for node %p (%s)\n", @@ -353,11 +353,11 @@ static int of_fill_overlay_info(struct of_overlay *ov, struct device_node *info_node, struct of_overlay_info *ovinfo) { ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__"); - if (ovinfo->overlay == NULL) + if (!ovinfo->overlay) goto err_fail; ovinfo->target = find_target_node(info_node); - if (ovinfo->target == NULL) + if (!ovinfo->target) goto err_fail; return 0; @@ -397,13 +397,13 @@ static int of_build_overlay_info(struct of_overlay *ov, cnt++; ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL); - if (ovinfo == NULL) + if (!ovinfo) return -ENOMEM; cnt = 0; for_each_child_of_node(tree, node) { err = of_fill_overlay_info(ov, node, &ovinfo[cnt]); - if (err == 0) + if (!err) cnt++; } @@ -421,7 +421,7 @@ static int of_build_overlay_info(struct of_overlay *ov, cnt++; } - if (cnt == 0) { + if (!cnt) { kfree(ovinfo); return -ENODEV; } @@ -477,7 +477,7 @@ int of_overlay_create(struct device_node *tree) int err, id; ov = kzalloc(sizeof(*ov), GFP_KERNEL); - if (ov == NULL) + if (!ov) return -ENOMEM; ov->id = -1; @@ -628,7 +628,7 @@ int of_overlay_destroy(int id) mutex_lock(&of_mutex); ov = idr_find(&ov_idr, id); - if (ov == NULL) { + if (!ov) { err = -ENODEV; pr_err("destroy: Could not find overlay #%d\n", id); goto out; From patchwork Tue Oct 17 01:17:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826686 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Cu+HTerD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHPf4X0yz9t2Q for ; Tue, 17 Oct 2017 12:18:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756601AbdJQBSM (ORCPT ); Mon, 16 Oct 2017 21:18:12 -0400 Received: from mail-pf0-f177.google.com ([209.85.192.177]:54024 "EHLO mail-pf0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754063AbdJQBSK (ORCPT ); Mon, 16 Oct 2017 21:18:10 -0400 Received: by mail-pf0-f177.google.com with SMTP id t188so112904pfd.10; Mon, 16 Oct 2017 18:18:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rgXUrEqY5j1gKjd2y5H7q4llQ5Jo7/dgz5JfMbyPCio=; b=Cu+HTerDtDmIF35jM429WqisHT6vTbvjMlZ58up4KooWGMIvPeehPnf+4uCvm5Qu/+ HZq5vq1LoTlpB3DsROpP9V4q2r/hmVM0zD7b9T+v7tNF5l8F/wLMktk9uTdRzyzOHeYQ K4MPp61tyzJBxGNjgmYyZeyTqSLyahmwoBJlyfe08whiv4JGshhzAZ5a7t0vTBeXEm5S RUNKlwav3ASInjqt0/SU4i6o1TD+n20YusHzom7pW8YnXwXUHyzHZBAeuRhgW6tds/ol jtwUnd1EfaK6oHbgnnoYEA5n/cCTqNH/Yynm12lGuKUd668ABWNAAbCoE7IT8Jn5G2/A HqnQ== 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:in-reply-to :references; bh=rgXUrEqY5j1gKjd2y5H7q4llQ5Jo7/dgz5JfMbyPCio=; b=KkXS3sXr7gv22tn+GrZyAap0OyQtZSct89XFAPlrARN3kw8grbgTGHM1KDJwoFsUSO jrZ9VxEKiTsHGUt1XyliWrRWD2Dirm8uZWyCn4irhLM9njaKNHV3hZ7MFScTDDOon79a 8AxxQk8anAZ7Zk+5Srp2KktoWNAVCyQrhZpZtBlBY7X3YGMZ+uZ9/DmmTlauSHrgKBFi HFx4HAwwHaLwU75kFPmV6g+BUGcOvjh33D3uqKKo3HMWYnObKSJbe2mT6iAr6OEjdrWu HA8YnkciXHto/dljlkKAVRsNoG9HSAuI1HiiV8rApeiPoOXDpwv23p6ez/PGz4sFFIVr C+gw== X-Gm-Message-State: AMCzsaXgdTerxaNOB5jay6wBKhx5/ILHwJDjZaqvizkZQ1QkAXcOXbGM hg4qcMKZ14FjQytdRle9icQ= X-Google-Smtp-Source: AOwi7QCsk7xP796Lc0fzL2La7ChtVBdg57gYXQCEeMwade1MhU6XHaiVZEE8gS90GJsEtEMJqbrs3w== X-Received: by 10.99.160.71 with SMTP id u7mr9594663pgn.22.1508203089062; Mon, 16 Oct 2017 18:18:09 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:08 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 03/12] of: overlay: rename identifiers to more reflect what they do Date: Mon, 16 Oct 2017 18:17:45 -0700 Message-Id: <1508203074-26917-4-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand This patch is aimed primarily at drivers/of/overlay.c, but those changes also have a small impact in a few other files. overlay.c is difficult to read and maintain. Improve readability: - Rename functions, types and variables to better reflect what they do and to be consistent with names in other places, such as the device tree overlay FDT (flattened device tree), and make the algorithms more clear - Use the same names consistently throughout the file - Update comments for name changes - Fix incorrect comments This patch is intended to not introduce any functional change. Signed-off-by: Frank Rowand --- Documentation/devicetree/overlay-notes.txt | 12 +- drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 5 +- drivers/of/dynamic.c | 2 +- drivers/of/overlay.c | 506 ++++++++++++++------------- drivers/of/unittest.c | 20 +- include/linux/of.h | 12 +- 6 files changed, 294 insertions(+), 263 deletions(-) diff --git a/Documentation/devicetree/overlay-notes.txt b/Documentation/devicetree/overlay-notes.txt index eb7f2685fda1..c4aa0adf13ec 100644 --- a/Documentation/devicetree/overlay-notes.txt +++ b/Documentation/devicetree/overlay-notes.txt @@ -87,15 +87,15 @@ Overlay in-kernel API The API is quite easy to use. -1. Call of_overlay_create() to create and apply an overlay. The return value -is a cookie identifying this overlay. +1. Call of_overlay_apply() to create and apply an overlay changeset. The return +value is an error or a cookie identifying this overlay. -2. Call of_overlay_destroy() to remove and cleanup the overlay previously -created via the call to of_overlay_create(). Removal of an overlay that -is stacked by another will not be permitted. +2. Call of_overlay_remove() to remove and cleanup the overlay changeset +previously created via the call to of_overlay_apply(). Removal of an overlay +changeset that is stacked by another will not be permitted. Finally, if you need to remove all overlays in one-go, just call -of_overlay_destroy_all() which will remove every single one in the correct +of_overlay_remove_all() which will remove every single one in the correct order. Overlay DTS Format diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 623a9140493c..5f5b7ba35f1d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -247,9 +247,10 @@ static void __init tilcdc_convert_slave_node(void) tilcdc_node_disable(slave); - ret = of_overlay_create(overlay); + ret = of_overlay_apply(overlay); if (ret) - pr_err("%s: Creating overlay failed: %d\n", __func__, ret); + pr_err("%s: Applying overlay changeset failed: %d\n", + __func__, ret); else pr_info("%s: ti,tilcdc,slave node successfully converted\n", __func__); diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 301b6db2b48d..124510d56421 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -775,7 +775,7 @@ int of_changeset_revert(struct of_changeset *ocs) EXPORT_SYMBOL_GPL(of_changeset_revert); /** - * of_changeset_action - Perform a changeset action + * of_changeset_action - Add an action to the tail of the changeset list * * @ocs: changeset pointer * @action: action to perform diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 8e0c7eb4858c..397ef10d1f26 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -25,67 +25,63 @@ #include "of_private.h" /** - * struct of_overlay_info - Holds a single overlay info + * struct fragment - info about fragment nodes in overlay expanded device tree * @target: target of the overlay operation - * @overlay: pointer to the overlay contents node - * - * Holds a single overlay state, including all the overlay logs & - * records. + * @overlay: pointer to the __overlay__ node */ -struct of_overlay_info { +struct fragment { struct device_node *target; struct device_node *overlay; bool is_symbols_node; }; /** - * struct of_overlay - Holds a complete overlay transaction - * @node: List on which we are located - * @count: Count of ovinfo structures - * @ovinfo_tab: Overlay info table (count sized) - * @cset: Changeset to be used - * - * Holds a complete overlay transaction + * struct overlay_changeset + * @ovcs_list: list on which we are located + * @count: count of @fragments structures + * @fragments: info about fragment nodes in overlay expanded device tree + * @cset: changeset to apply fragments to live device tree */ -struct of_overlay { +struct overlay_changeset { int id; - struct list_head node; + struct list_head ovcs_list; int count; - struct of_overlay_info *ovinfo_tab; + struct fragment *fragments; struct of_changeset cset; }; -static int of_overlay_apply_one(struct of_overlay *ov, - struct device_node *target, const struct device_node *overlay, +static int build_changeset_next_level(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_node, bool is_symbols_node); -static BLOCKING_NOTIFIER_HEAD(of_overlay_chain); +static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain); int of_overlay_notifier_register(struct notifier_block *nb) { - return blocking_notifier_chain_register(&of_overlay_chain, nb); + return blocking_notifier_chain_register(&overlay_notify_chain, nb); } EXPORT_SYMBOL_GPL(of_overlay_notifier_register); int of_overlay_notifier_unregister(struct notifier_block *nb) { - return blocking_notifier_chain_unregister(&of_overlay_chain, nb); + return blocking_notifier_chain_unregister(&overlay_notify_chain, nb); } EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister); -static int of_overlay_notify(struct of_overlay *ov, - enum of_overlay_notify_action action) +static int overlay_notify(struct overlay_changeset *ovcs, + enum of_overlay_notify_action action) { struct of_overlay_notify_data nd; int i, ret; - for (i = 0; i < ov->count; i++) { - struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; + for (i = 0; i < ovcs->count; i++) { + struct fragment *fragment = &ovcs->fragments[i]; - nd.target = ovinfo->target; - nd.overlay = ovinfo->overlay; + nd.target = fragment->target; + nd.overlay = fragment->overlay; - ret = blocking_notifier_call_chain(&of_overlay_chain, + ret = blocking_notifier_call_chain(&overlay_notify_chain, action, &nd); if (ret) return notifier_to_errno(ret); @@ -94,10 +90,10 @@ static int of_overlay_notify(struct of_overlay *ov, return 0; } -static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, - const struct property *prop) +static struct property *dup_and_fixup_symbol_prop( + struct overlay_changeset *ovcs, const struct property *prop) { - struct of_overlay_info *ovinfo; + struct fragment *fragment; struct property *new; const char *overlay_name; char *label_path; @@ -116,18 +112,18 @@ static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, if (!new) return NULL; - for (k = 0; k < ov->count; k++) { - ovinfo = &ov->ovinfo_tab[k]; - overlay_name = ovinfo->overlay->full_name; + for (k = 0; k < ovcs->count; k++) { + fragment = &ovcs->fragments[k]; + overlay_name = fragment->overlay->full_name; overlay_name_len = strlen(overlay_name); if (!strncasecmp(symbol_path, overlay_name, overlay_name_len)) break; } - if (k >= ov->count) + if (k >= ovcs->count) goto err_free; - target_path = ovinfo->target->full_name; + target_path = fragment->target->full_name; target_path_len = strlen(target_path); label_path = symbol_path + overlay_name_len; @@ -156,81 +152,110 @@ static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov, } -/* +/** + * add_changeset_property() - add @overlay_prop to overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @overlay_prop in live tree + * @overlay_prop: property to add or update, from overlay tree + * is_symbols_node: 1 if @target_node is "/__symbols__" + * + * If @overlay_prop does not already exist in @target_node, add changeset entry + * to add @overlay_prop in @target_node, else add changeset entry to update + * value of @overlay_prop. + * * Some special properties are not updated (no error returned). + * * Update of property in symbols node is not allowed. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. */ -static int of_overlay_apply_single_property(struct of_overlay *ov, - struct device_node *target, struct property *prop, +static int add_changeset_property(struct overlay_changeset *ovcs, + struct device_node *target_node, + struct property *overlay_prop, bool is_symbols_node) { - struct property *propn = NULL, *tprop; + struct property *new_prop = NULL, *prop; - tprop = of_find_property(target, prop->name, NULL); + prop = of_find_property(target_node, overlay_prop->name, NULL); - if (!of_prop_cmp(prop->name, "name") || - !of_prop_cmp(prop->name, "phandle") || - !of_prop_cmp(prop->name, "linux,phandle")) + if (!of_prop_cmp(overlay_prop->name, "name") || + !of_prop_cmp(overlay_prop->name, "phandle") || + !of_prop_cmp(overlay_prop->name, "linux,phandle")) return 0; if (is_symbols_node) { - if (tprop) + if (prop) return -EINVAL; - propn = dup_and_fixup_symbol_prop(ov, prop); + new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop); } else { - propn = __of_prop_dup(prop, GFP_KERNEL); + new_prop = __of_prop_dup(overlay_prop, GFP_KERNEL); } - if (!propn) + if (!new_prop) return -ENOMEM; - if (!tprop) - return of_changeset_add_property(&ov->cset, target, propn); + if (!prop) + return of_changeset_add_property(&ovcs->cset, target_node, + new_prop); - return of_changeset_update_property(&ov->cset, target, propn); + return of_changeset_update_property(&ovcs->cset, target_node, new_prop); } -/* +/** + * add_changeset_node() - add @node (and children) to overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @node in live tree + * @node: node from within overlay device tree fragment + * + * If @node does not already exist in @target_node, add changeset entry + * to add @node in @target_node. + * + * If @node already exists in @target_node, and the existing node has + * a phandle, the overlay node is not allowed to have a phandle. + * + * If @node has child nodes, add the children recursively via + * build_changeset_next_level(). + * * NOTE: Multiple mods of created nodes not supported. * - * Return - * -ENOMEM if memory allocation fails - * -EINVAL if existing node has a phandle and overlay node has a phandle + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. */ -static int of_overlay_apply_single_device_node(struct of_overlay *ov, - struct device_node *target, struct device_node *child) +static int add_changeset_node(struct overlay_changeset *ovcs, + struct device_node *target_node, struct device_node *node) { - const char *cname; + const char *node_kbasename; struct device_node *tchild; int ret = 0; - cname = kbasename(child->full_name); - if (!cname) + node_kbasename = kbasename(node->full_name); + if (!node_kbasename) return -ENOMEM; - for_each_child_of_node(target, tchild) - if (!of_node_cmp(cname, kbasename(tchild->full_name))) + for_each_child_of_node(target_node, tchild) + if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) break; if (tchild) { - if (child->phandle) + if (node->phandle) return -EINVAL; - /* apply overlay recursively */ - ret = of_overlay_apply_one(ov, tchild, child, 0); + ret = build_changeset_next_level(ovcs, tchild, node, 0); of_node_put(tchild); } else { - tchild = __of_node_dup(child, "%pOF/%s", target, cname); + tchild = __of_node_dup(node, "%pOF/%s", + target_node, node_kbasename); if (!tchild) return -ENOMEM; - tchild->parent = target; + tchild->parent = target_node; - ret = of_changeset_attach_node(&ov->cset, tchild); + ret = of_changeset_attach_node(&ovcs->cset, tchild); if (ret) return ret; - ret = of_overlay_apply_one(ov, tchild, child, 0); + ret = build_changeset_next_level(ovcs, tchild, node, 0); if (ret) return ret; } @@ -238,29 +263,37 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov, return ret; } -/* - * Apply a single overlay node recursively. +/** + * build_changeset_next_level() - add level of overlay changeset + * @ovcs: overlay changeset + * @target_node: where to place @overlay_node in live tree + * @overlay_node: node from within an overlay device tree fragment + * @is_symbols_node: @overlay_node is node "/__symbols__" * - * Note that the in case of an error the target node is left - * in a inconsistent state. Error recovery should be performed - * by using the changeset. + * Add the properties (if any) and nodes (if any) from @overlay_node to the + * @ovcs->cset changeset. If an added node has child nodes, they will + * be added recursively. * * Do not allow symbols node to have any children. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay_node. */ -static int of_overlay_apply_one(struct of_overlay *ov, - struct device_node *target, const struct device_node *overlay, +static int build_changeset_next_level(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_node, bool is_symbols_node) { struct device_node *child; struct property *prop; int ret; - for_each_property_of_node(overlay, prop) { - ret = of_overlay_apply_single_property(ov, target, prop, - is_symbols_node); + for_each_property_of_node(overlay_node, prop) { + ret = add_changeset_property(ovcs, target_node, prop, + is_symbols_node); if (ret) { pr_err("Failed to apply prop @%pOF/%s\n", - target, prop->name); + target_node, prop->name); return ret; } } @@ -268,11 +301,11 @@ static int of_overlay_apply_one(struct of_overlay *ov, if (is_symbols_node) return 0; - for_each_child_of_node(overlay, child) { - ret = of_overlay_apply_single_device_node(ov, target, child); + for_each_child_of_node(overlay_node, child) { + ret = add_changeset_node(ovcs, target_node, child); if (ret) { - pr_err("Failed to apply single node @%pOF/%s\n", - target, child->name); + pr_err("Failed to apply node @%pOF/%s\n", + target_node, child->name); of_node_put(child); return ret; } @@ -282,26 +315,30 @@ static int of_overlay_apply_one(struct of_overlay *ov, } /** - * of_overlay_apply() - Apply @count overlays pointed at by @ovinfo_tab - * @ov: Overlay to apply + * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments + * @ovcs: Overlay changeset * - * Applies the overlays given, while handling all error conditions - * appropriately. Either the operation succeeds, or if it fails the - * live tree is reverted to the state before the attempt. - * Returns 0, or an error if the overlay attempt failed. + * Create changeset @ovcs->cset to contain the nodes and properties of the + * overlay device tree fragments in @ovcs->fragments[]. If an error occurs, + * any portions of the changeset that were successfully created will remain + * in @ovcs->cset. + * + * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid overlay in @ovcs->fragments[]. */ -static int of_overlay_apply(struct of_overlay *ov) +static int build_changeset(struct overlay_changeset *ovcs) { - int i, err; + int i, ret; - for (i = 0; i < ov->count; i++) { - struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; + for (i = 0; i < ovcs->count; i++) { + struct fragment *fragment = &ovcs->fragments[i]; - err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay, - ovinfo->is_symbols_node); - if (err) { - pr_err("apply failed '%pOF'\n", ovinfo->target); - return err; + ret = build_changeset_next_level(ovcs, fragment->target, + fragment->overlay, + fragment->is_symbols_node); + if (ret) { + pr_err("apply failed '%pOF'\n", fragment->target); + return ret; } } @@ -371,23 +408,24 @@ static int of_fill_overlay_info(struct of_overlay *ov, } /** - * of_build_overlay_info() - Build an overlay info array - * @ov Overlay to build - * @tree: Device node containing all the overlays + * init_overlay_changeset() - initialize overlay changeset from overlay tree + * @ovcs Overlay changeset to build + * @tree: Contains all the overlay fragments and overlay fixup nodes * - * Helper function that given a tree containing overlay information, - * allocates and builds an overlay info array containing it, ready - * for use using of_overlay_apply. + * Initialize @ovcs. Populate @ovcs->fragments with node information from + * the top level of @tree. The relevant top level nodes are the fragment + * nodes and the __symbols__ node. Any other top level node will be ignored. * - * Returns 0 on success with the @cntp @ovinfop pointers valid, - * while on error a negative error value is returned. + * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error + * detected in @tree, or -ENODEV if no valid nodes found. */ -static int of_build_overlay_info(struct of_overlay *ov, +static int init_overlay_changeset(struct overlay_changeset *ovcs, struct device_node *tree) { struct device_node *node; - struct of_overlay_info *ovinfo; - int cnt, err; + struct fragment *fragment; + struct fragment *fragments; + int cnt, ret; cnt = 0; for_each_child_of_node(tree, node) @@ -396,24 +434,25 @@ static int of_build_overlay_info(struct of_overlay *ov, if (of_get_child_by_name(tree, "__symbols__")) cnt++; - ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL); - if (!ovinfo) + fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL); + if (!fragments) return -ENOMEM; cnt = 0; for_each_child_of_node(tree, node) { - err = of_fill_overlay_info(ov, node, &ovinfo[cnt]); - if (!err) + ret = of_fill_overlay_info(ovcs, node, &fragments[cnt]); + if (!ret) cnt++; } node = of_get_child_by_name(tree, "__symbols__"); if (node) { - ovinfo[cnt].overlay = node; - ovinfo[cnt].target = of_find_node_by_path("/__symbols__"); - ovinfo[cnt].is_symbols_node = 1; + fragment = &fragments[cnt]; + fragment->overlay = node; + fragment->target = of_find_node_by_path("/__symbols__"); + fragment->is_symbols_node = 1; - if (!ovinfo[cnt].target) { + if (!fragment->target) { pr_err("no symbols in root of device tree.\n"); return -EINVAL; } @@ -422,137 +461,127 @@ static int of_build_overlay_info(struct of_overlay *ov, } if (!cnt) { - kfree(ovinfo); + kfree(fragments); return -ENODEV; } - ov->count = cnt; - ov->ovinfo_tab = ovinfo; + ovcs->count = cnt; + ovcs->fragments = fragments; return 0; } /** - * of_free_overlay_info() - Free an overlay info array - * @ov Overlay to free the overlay info from - * @ovinfo_tab: Array of overlay_info's to free + * free_overlay_fragments() - Free a fragments array + * @ovcs Overlay to free the overlay info from * - * Releases the memory of a previously allocated ovinfo array - * by of_build_overlay_info. - * Returns 0, or an error if the arguments are bogus. + * Frees the memory of an ovcs->fragments[] array. */ -static int of_free_overlay_info(struct of_overlay *ov) +static void free_overlay_fragments(struct overlay_changeset *ovcs) { - struct of_overlay_info *ovinfo; int i; /* do it in reverse */ - for (i = ov->count - 1; i >= 0; i--) { - ovinfo = &ov->ovinfo_tab[i]; - - of_node_put(ovinfo->target); - of_node_put(ovinfo->overlay); + for (i = ovcs->count - 1; i >= 0; i--) { + of_node_put(ovcs->fragments[i].target); + of_node_put(ovcs->fragments[i].overlay); } - kfree(ov->ovinfo_tab); - return 0; + kfree(ovcs->fragments); } -static LIST_HEAD(ov_list); -static DEFINE_IDR(ov_idr); +static LIST_HEAD(ovcs_list); +static DEFINE_IDR(ovcs_idr); /** - * of_overlay_create() - Create and apply an overlay - * @tree: Device node containing all the overlays + * of_overlay_apply() - Create and apply an overlay changeset + * @tree: Expanded overlay device tree * - * Creates and applies an overlay while also keeping track - * of the overlay in a list. This list can be used to prevent - * illegal overlay removals. + * Creates and applies an overlay changeset. If successful, the overlay + * changeset is added to the overlay changeset list. * - * Returns the id of the created overlay, or a negative error number + * Returns the id of the created overlay changeset, or a negative error number */ -int of_overlay_create(struct device_node *tree) +int of_overlay_apply(struct device_node *tree) { - struct of_overlay *ov; - int err, id; + struct overlay_changeset *ovcs; + int id, ret; - ov = kzalloc(sizeof(*ov), GFP_KERNEL); - if (!ov) + ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); + if (!ovcs) return -ENOMEM; - ov->id = -1; + ovcs->id = -1; - INIT_LIST_HEAD(&ov->node); + INIT_LIST_HEAD(&ovcs->ovcs_list); - of_changeset_init(&ov->cset); + of_changeset_init(&ovcs->cset); mutex_lock(&of_mutex); - id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL); + id = idr_alloc(&ovcs_idr, ovcs, 0, 0, GFP_KERNEL); if (id < 0) { - err = id; + ret = id; goto err_destroy_trans; } - ov->id = id; + ovcs->id = id; - err = of_build_overlay_info(ov, tree); - if (err) { - pr_err("of_build_overlay_info() failed for tree@%pOF\n", + ret = init_overlay_changeset(ovcs, tree); + if (ret) { + pr_err("init_overlay_changeset() failed for tree@%pOF\n", tree); goto err_free_idr; } - err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY); - if (err < 0) { - pr_err("%s: Pre-apply notifier failed (err=%d)\n", - __func__, err); - goto err_free_idr; + ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); + if (ret < 0) { + pr_err("%s: Pre-apply notifier failed (ret=%d)\n", + __func__, ret); + goto err_free_overlay_fragments; } - err = of_overlay_apply(ov); - if (err) - goto err_abort_trans; + ret = build_changeset(ovcs); + if (ret) + goto err_free_overlay_fragments; - err = __of_changeset_apply(&ov->cset); - if (err) - goto err_revert_overlay; + ret = __of_changeset_apply(&ovcs->cset); + if (ret) + goto err_free_overlay_fragments; + list_add_tail(&ovcs->ovcs_list, &ovcs_list); - list_add_tail(&ov->node, &ov_list); - - of_overlay_notify(ov, OF_OVERLAY_POST_APPLY); + overlay_notify(ovcs, OF_OVERLAY_POST_APPLY); mutex_unlock(&of_mutex); return id; -err_revert_overlay: -err_abort_trans: - of_free_overlay_info(ov); +err_free_overlay_fragments: + free_overlay_fragments(ovcs); err_free_idr: - idr_remove(&ov_idr, ov->id); + idr_remove(&ovcs_idr, ovcs->id); err_destroy_trans: - of_changeset_destroy(&ov->cset); - kfree(ov); + of_changeset_destroy(&ovcs->cset); + kfree(ovcs); mutex_unlock(&of_mutex); - return err; + return ret; } -EXPORT_SYMBOL_GPL(of_overlay_create); +EXPORT_SYMBOL_GPL(of_overlay_apply); /* - * check whether the given node, lies under the given tree - * return 1 if under tree, else 0 + * Find @np in @tree. + * + * Returns 1 if @np is @tree or is contained in @tree, else 0 */ -static int overlay_subtree_check(struct device_node *tree, - struct device_node *dn) +static int find_node(struct device_node *tree, struct device_node *np) { struct device_node *child; - if (tree == dn) + if (tree == np) return 1; for_each_child_of_node(tree, child) { - if (overlay_subtree_check(child, dn)) { + if (find_node(child, np)) { of_node_put(child); return 1; } @@ -562,30 +591,32 @@ static int overlay_subtree_check(struct device_node *tree, } /* - * check whether this overlay is the topmost - * return 1 if topmost, else 0 + * Is @remove_ce_np a child of or the same as any + * node in an overlay changeset more topmost than @remove_ovcs? + * + * Returns 1 if found, else 0 */ -static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) +static int node_in_later_cs(struct overlay_changeset *remove_ovcs, + struct device_node *remove_ce_np) { - struct of_overlay *ovt; + struct overlay_changeset *ovcs; struct of_changeset_entry *ce; - list_for_each_entry_reverse(ovt, &ov_list, node) { - /* if we hit ourselves, we're done */ - if (ovt == ov) + list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) { + if (ovcs == remove_ovcs) break; - /* check against each subtree affected by this overlay */ - list_for_each_entry(ce, &ovt->cset.entries, node) { - if (overlay_subtree_check(ce->np, dn)) { + list_for_each_entry(ce, &ovcs->cset.entries, node) { + if (find_node(ce->np, remove_ce_np)) { pr_err("%s: #%d clashes #%d @%pOF\n", - __func__, ov->id, ovt->id, dn); - return 0; + __func__, remove_ovcs->id, ovcs->id, + remove_ce_np); + return 1; } } } - return 1; + return 0; } /* @@ -598,13 +629,13 @@ static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) * the one closest to the tail. If another overlay has affected this * device node and is closest to the tail, then removal is not permited. */ -static int overlay_removal_is_ok(struct of_overlay *ov) +static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) { - struct of_changeset_entry *ce; + struct of_changeset_entry *remove_ce; - list_for_each_entry(ce, &ov->cset.entries, node) { - if (!overlay_is_topmost(ov, ce->np)) { - pr_err("overlay #%d is not topmost\n", ov->id); + list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) { + if (node_in_later_cs(remove_ovcs, remove_ce->np)) { + pr_err("overlay #%d is not topmost\n", remove_ovcs->id); return 0; } } @@ -613,74 +644,73 @@ static int overlay_removal_is_ok(struct of_overlay *ov) } /** - * of_overlay_destroy() - Removes an overlay - * @id: Overlay id number returned by a previous call to of_overlay_create + * of_overlay_remove() - Revert and free an overlay changeset + * @ovcs_id: Overlay changeset id number * - * Removes an overlay if it is permissible. + * Removes an overlay if it is permissible. ovcs_id was previously returned + * by of_overlay_apply(). * * Returns 0 on success, or a negative error number */ -int of_overlay_destroy(int id) +int of_overlay_remove(int ovcs_id) { - struct of_overlay *ov; - int err; + struct overlay_changeset *ovcs; + int ret = 0; mutex_lock(&of_mutex); - ov = idr_find(&ov_idr, id); - if (!ov) { - err = -ENODEV; - pr_err("destroy: Could not find overlay #%d\n", id); + ovcs = idr_find(&ovcs_idr, ovcs_id); + if (!ovcs) { + ret = -ENODEV; + pr_err("remove: Could not find overlay #%d\n", ovcs_id); goto out; } - if (!overlay_removal_is_ok(ov)) { - err = -EBUSY; + if (!overlay_removal_is_ok(ovcs)) { + ret = -EBUSY; goto out; } - of_overlay_notify(ov, OF_OVERLAY_PRE_REMOVE); - list_del(&ov->node); - __of_changeset_revert(&ov->cset); - of_overlay_notify(ov, OF_OVERLAY_POST_REMOVE); - of_free_overlay_info(ov); - idr_remove(&ov_idr, id); - of_changeset_destroy(&ov->cset); - kfree(ov); - - err = 0; + overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); + list_del(&ovcs->ovcs_list); + __of_changeset_revert(&ovcs->cset); + overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); + free_overlay_fragments(ovcs); + idr_remove(&ovcs_idr, ovcs_id); + of_changeset_destroy(&ovcs->cset); + kfree(ovcs); out: mutex_unlock(&of_mutex); - return err; + return ret; } -EXPORT_SYMBOL_GPL(of_overlay_destroy); +EXPORT_SYMBOL_GPL(of_overlay_remove); /** - * of_overlay_destroy_all() - Removes all overlays from the system + * of_overlay_remove_all() - Reverts and frees all overlay changesets * * Removes all overlays from the system in the correct order. * * Returns 0 on success, or a negative error number */ -int of_overlay_destroy_all(void) +int of_overlay_remove_all(void) { - struct of_overlay *ov, *ovn; + struct overlay_changeset *ovcs, *ovcs_n; mutex_lock(&of_mutex); /* the tail of list is guaranteed to be safe to remove */ - list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) { - list_del(&ov->node); - __of_changeset_revert(&ov->cset); - of_free_overlay_info(ov); - idr_remove(&ov_idr, ov->id); - kfree(ov); + list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) { + list_del(&ovcs->ovcs_list); + __of_changeset_revert(&ovcs->cset); + free_overlay_fragments(ovcs); + idr_remove(&ovcs_idr, ovcs->id); + kfree(ovcs); } mutex_unlock(&of_mutex); return 0; } -EXPORT_SYMBOL_GPL(of_overlay_destroy_all); +EXPORT_SYMBOL_GPL(of_overlay_remove_all); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 29a35cb1da64..e19dcd80e7a7 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1231,7 +1231,7 @@ static void of_unittest_destroy_tracked_overlays(void) if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id))) continue; - ret = of_overlay_destroy(id + overlay_first_id); + ret = of_overlay_remove(id + overlay_first_id); if (ret == -ENODEV) { pr_warn("%s: no overlay to destroy for #%d\n", __func__, id + overlay_first_id); @@ -1263,7 +1263,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, goto out; } - ret = of_overlay_create(np); + ret = of_overlay_apply(np); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr)); @@ -1348,7 +1348,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, return -EINVAL; } - ret = of_overlay_destroy(ov_id); + ret = of_overlay_remove(ov_id); if (ret != 0) { unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", overlay_path(overlay_nr), @@ -1477,7 +1477,7 @@ static void of_unittest_overlay_6(void) return; } - ret = of_overlay_create(np); + ret = of_overlay_apply(np); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); @@ -1501,7 +1501,7 @@ static void of_unittest_overlay_6(void) } for (i = 1; i >= 0; i--) { - ret = of_overlay_destroy(ov_id[i]); + ret = of_overlay_remove(ov_id[i]); if (ret != 0) { unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", overlay_path(overlay_nr + i), @@ -1547,7 +1547,7 @@ static void of_unittest_overlay_8(void) return; } - ret = of_overlay_create(np); + ret = of_overlay_apply(np); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); @@ -1558,7 +1558,7 @@ static void of_unittest_overlay_8(void) } /* now try to remove first overlay (it should fail) */ - ret = of_overlay_destroy(ov_id[0]); + ret = of_overlay_remove(ov_id[0]); if (ret == 0) { unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", overlay_path(overlay_nr + 0), @@ -1569,7 +1569,7 @@ static void of_unittest_overlay_8(void) /* removing them in order should work */ for (i = 1; i >= 0; i--) { - ret = of_overlay_destroy(ov_id[i]); + ret = of_overlay_remove(ov_id[i]); if (ret != 0) { unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", overlay_path(overlay_nr + i), @@ -2151,9 +2151,9 @@ static int __init overlay_data_add(int onum) goto out_free_np_overlay; } - ret = of_overlay_create(info->np_overlay); + ret = of_overlay_apply(info->np_overlay); if (ret < 0) { - pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum); + pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); goto out_free_np_overlay; } else { info->overlay_id = ret; diff --git a/include/linux/of.h b/include/linux/of.h index cfc34117fc92..45e787e28ce7 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1306,26 +1306,26 @@ struct of_overlay_notify_data { #ifdef CONFIG_OF_OVERLAY /* ID based overlays; the API for external users */ -int of_overlay_create(struct device_node *tree); -int of_overlay_destroy(int id); -int of_overlay_destroy_all(void); +int of_overlay_apply(struct device_node *tree); +int of_overlay_remove(int id); +int of_overlay_remove_all(void); int of_overlay_notifier_register(struct notifier_block *nb); int of_overlay_notifier_unregister(struct notifier_block *nb); #else -static inline int of_overlay_create(struct device_node *tree) +static inline int of_overlay_apply(struct device_node *tree) { return -ENOTSUPP; } -static inline int of_overlay_destroy(int id) +static inline int of_overlay_remove(int id) { return -ENOTSUPP; } -static inline int of_overlay_destroy_all(void) +static inline int of_overlay_remove_all(void) { return -ENOTSUPP; } From patchwork Tue Oct 17 01:17:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826700 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YJFNW7Hr"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHTN1yyjz9s82 for ; Tue, 17 Oct 2017 12:21:28 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752651AbdJQBVM (ORCPT ); Mon, 16 Oct 2017 21:21:12 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:50853 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756582AbdJQBSL (ORCPT ); Mon, 16 Oct 2017 21:18:11 -0400 Received: by mail-pg0-f67.google.com with SMTP id y7so122994pgb.7; Mon, 16 Oct 2017 18:18:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zxfLElnPI+lls7EFcik683Rnsy7tcOpk2BAfSegbJkI=; b=YJFNW7HrJ7Ou9q9W0NXw73llEdZ43dflCH8fXnqFtobtrWr2cAJqX2G01AHDADmQJR NSR61+8vkFMQ5wZANYqp/jgQzroyqyuFW/zxfx0U//zdoNWLN9VZX09nLB3zE5ANzdKv lZGrJ9G9S4dFYGaG+5T95oA1v1ywYba6oj4ZCIWBOsi6NlmCmZXykAOm0PulSzxHUGKo tsyvNMk3kaROipgfmnazDZvOg9u9yG46AyRCnuHz5Tbq1esbJ3FjV7V5/iMTU/dn/jqe R3MnDZaXioaZdRawNDut7s0Gh7kVIt7EJqkB+kfTpM1L7zF1kEhBh8ZKw2z3ErVyJ+/E hx2w== 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:in-reply-to :references; bh=zxfLElnPI+lls7EFcik683Rnsy7tcOpk2BAfSegbJkI=; b=aQXeqongjhv2eDhsn+l+6bnuu883e96ejgtyOrlVmmUBU0R1VYwpmHBsiageQjCJeS LL7Qss/LAO9PH56bdIbJr7y+V9D9lCpEeZH2F6jgt84WFb5fDAuhvbSNx1ZKDVYUdcJC Y130v3dxYS9K2HsdSVbDR5vF9OcHfGa80BwYogt5B6vQL9JATYUYYg6qDnUfQmoakHCe qw42pzbsiBlL3AqUA2giAvp4nPtEt+WnR158nXPCqidpNoToCNNCFUp84NrP2aTAhTeT 8qVUBR7r3RZapuvFlQJgZH3Qu1xk4WOKHIba2fnE6GXFE1tFul4nDAvbPWPvE7hCSDzL y2VA== X-Gm-Message-State: AMCzsaUhgu6p0xbGpvHCCEITyHw8AMWEgL1SVEQgIKs1bSILYYz+FmcD C1xhFbaoCB3eJMaef8UBPQE= X-Google-Smtp-Source: AOwi7QBwaUjmpRKj/Hfc22aITlXn91sM8V85jkzVT3inRVZe4GFRM7KmIHgNo7NQj8XqJS1eCr5noA== X-Received: by 10.98.131.197 with SMTP id h188mr10071710pfe.224.1508203090926; Mon, 16 Oct 2017 18:18:10 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:10 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 04/12] of: overlay: rename identifiers in dup_and_fixup_symbol_prop() Date: Mon, 16 Oct 2017 18:17:46 -0700 Message-Id: <1508203074-26917-5-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand More renaming of identifiers to better reflect what they do. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 397ef10d1f26..c350742ed2a2 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -90,17 +90,29 @@ static int overlay_notify(struct overlay_changeset *ovcs, return 0; } +/* + * The properties in the "/__symbols__" node are "symbols". + * + * The value of properties in the "/__symbols__" node is the path of a + * node in the subtree of a fragment node's "__overlay__" node, for + * example "/fragment@0/__overlay__/symbol_path_tail". Symbol_path_tail + * can be a single node or it may be a multi-node path. + * + * The duplicated property value will be modified by replacing the + * "/fragment_name/__overlay/" portion of the value with the target + * path from the fragment node. + */ static struct property *dup_and_fixup_symbol_prop( struct overlay_changeset *ovcs, const struct property *prop) { struct fragment *fragment; struct property *new; const char *overlay_name; - char *label_path; + char *symbol_path_tail; char *symbol_path; const char *target_path; int k; - int label_path_len; + int symbol_path_tail_len; int overlay_name_len; int target_path_len; @@ -126,18 +138,18 @@ static struct property *dup_and_fixup_symbol_prop( target_path = fragment->target->full_name; target_path_len = strlen(target_path); - label_path = symbol_path + overlay_name_len; - label_path_len = strlen(label_path); + symbol_path_tail = symbol_path + overlay_name_len; + symbol_path_tail_len = strlen(symbol_path_tail); new->name = kstrdup(prop->name, GFP_KERNEL); - new->length = target_path_len + label_path_len + 1; + new->length = target_path_len + symbol_path_tail_len + 1; new->value = kzalloc(new->length, GFP_KERNEL); if (!new->name || !new->value) goto err_free; strcpy(new->value, target_path); - strcpy(new->value + target_path_len, label_path); + strcpy(new->value + target_path_len, symbol_path_tail); of_property_set_flag(new, OF_DYNAMIC); From patchwork Tue Oct 17 01:17:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826699 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="eRV0lArm"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHSx70ZPz9sPk for ; Tue, 17 Oct 2017 12:21:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754821AbdJQBUM (ORCPT ); Mon, 16 Oct 2017 21:20:12 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:51859 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756547AbdJQBSM (ORCPT ); Mon, 16 Oct 2017 21:18:12 -0400 Received: by mail-pf0-f193.google.com with SMTP id n14so115981pfh.8; Mon, 16 Oct 2017 18:18:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=p0KjzC/8CzfXCpspck177kB0yXtgh1Hk0g6Hu+OeMjU=; b=eRV0lArmpxMwYqWEVwMgiwEPDq3NbMI/0AfQYUupzvbGvcFCwWAdmPJCu6fcf2kT1M SiiYWyvGtCRcajMj16tZwDxrFWPN6gXu8/FYsg7E22nOW0XHwSIKr5KkoXo8huIEZI3j KCAXPDtZztPalmZDQGX1TwjFl8yb8ndXk+flcHfWjyWd+NicfiaMe37WZQKsQDeCFbgW dE0YElWqXgw/XgGfBhTYJEuGZetFc6RzCI6wVWnH8rdLDrX/iZgTgTs+VbYDO0Vx4ybS YrkEvjW+m/s3PGa9LFGvj/tYmLeFEo1G+YtPV04mCCidM/S/OJZ4VrbFTVsdV4GwitU2 66UQ== 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:in-reply-to :references; bh=p0KjzC/8CzfXCpspck177kB0yXtgh1Hk0g6Hu+OeMjU=; b=nvMhOlm6FH3pw4e8UvvXnbVU6LwsuxKyLBwjAICXVXxM3ZLxMr7nArtjozr3J+1I2w lu38jAQ8ueftkv050LjqOXSCVlGVhGYreC5dVXzdqX5vwfMZnzdDwYwicAIUygMBssJM FyHAj1K0x2oyIdvK+RF5w/t6fKnOOv1Ctb5LwXiYgg4FtklUsn1PULE+xU8FjzoxY3zn 66acyLm02bjWcz9RDDXQfAf/Rf/C6h6R6wuY/ISxnNSz464KikyrhZHRYJIC+mZBo8/M avn2Bmjwe8TJ0vRd5mbInDkfdeuqxP6DkrPCsp2NDKPx2GbXeHKAs+aXO6S24PUwxsMi ZL/A== X-Gm-Message-State: AMCzsaVHnOOAgQdDSODlNeBJmh2CnTmy9oL9fhKFEcZWptAxnaCI4hnF c4gC56Bctrh/qPyNPTYwfEs= X-Google-Smtp-Source: AOwi7QDRlW/ERqFOAlWgwpjjc5UhHnmgdmqCrPaDBa5FT3x1hd0u+Ee7XjF8BrfFjE6p15poRgjgNg== X-Received: by 10.98.158.6 with SMTP id s6mr10357129pfd.191.1508203092135; Mon, 16 Oct 2017 18:18:12 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:11 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 05/12] of: overlay: minor restructuring Date: Mon, 16 Oct 2017 18:17:47 -0700 Message-Id: <1508203074-26917-6-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand Continue improving the readability of overlay.c. The previous patches renamed identifiers. This patch is split out from the previous patches to make the previous patches easier to review. Changes are: - minor code restructuring - some initialization of an overlay changeset occurred outside of init_overlay_changeset(), move that into init_overlay_changeset() - consolidate freeing an overlay changeset into free_overlay_changeset() This patch is intended to not introduce any functional change. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 205 +++++++++++++++++++++++---------------------------- 1 file changed, 92 insertions(+), 113 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index c350742ed2a2..0f92a5c26748 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -55,6 +55,9 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, const struct device_node *overlay_node, bool is_symbols_node); +static LIST_HEAD(ovcs_list); +static DEFINE_IDR(ovcs_idr); + static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain); int of_overlay_notifier_register(struct notifier_block *nb) @@ -160,8 +163,6 @@ static struct property *dup_and_fixup_symbol_prop( kfree(new->value); kfree(new); return NULL; - - } /** @@ -249,13 +250,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs, if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) break; - if (tchild) { - if (node->phandle) - return -EINVAL; - - ret = build_changeset_next_level(ovcs, tchild, node, 0); - of_node_put(tchild); - } else { + if (!tchild) { tchild = __of_node_dup(node, "%pOF/%s", target_node, node_kbasename); if (!tchild) @@ -267,11 +262,15 @@ static int add_changeset_node(struct overlay_changeset *ovcs, if (ret) return ret; - ret = build_changeset_next_level(ovcs, tchild, node, 0); - if (ret) - return ret; + return build_changeset_next_level(ovcs, tchild, node, 0); } + if (node->phandle) + return -EINVAL; + + ret = build_changeset_next_level(ovcs, tchild, node, 0); + of_node_put(tchild); + return ret; } @@ -385,41 +384,6 @@ static struct device_node *find_target_node(struct device_node *info_node) } /** - * of_fill_overlay_info() - Fill an overlay info structure - * @ov Overlay to fill - * @info_node: Device node containing the overlay - * @ovinfo: Pointer to the overlay info structure to fill - * - * Fills an overlay info structure with the overlay information - * from a device node. This device node must have a target property - * which contains a phandle of the overlay target node, and an - * __overlay__ child node which has the overlay contents. - * Both ovinfo->target & ovinfo->overlay have their references taken. - * - * Returns 0 on success, or a negative error value. - */ -static int of_fill_overlay_info(struct of_overlay *ov, - struct device_node *info_node, struct of_overlay_info *ovinfo) -{ - ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__"); - if (!ovinfo->overlay) - goto err_fail; - - ovinfo->target = find_target_node(info_node); - if (!ovinfo->target) - goto err_fail; - - return 0; - -err_fail: - of_node_put(ovinfo->target); - of_node_put(ovinfo->overlay); - - memset(ovinfo, 0, sizeof(*ovinfo)); - return -EINVAL; -} - -/** * init_overlay_changeset() - initialize overlay changeset from overlay tree * @ovcs Overlay changeset to build * @tree: Contains all the overlay fragments and overlay fixup nodes @@ -429,32 +393,61 @@ static int of_fill_overlay_info(struct of_overlay *ov, * nodes and the __symbols__ node. Any other top level node will be ignored. * * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error - * detected in @tree, or -ENODEV if no valid nodes found. + * detected in @tree, or -ENOSPC if idr_alloc() error. */ static int init_overlay_changeset(struct overlay_changeset *ovcs, struct device_node *tree) { - struct device_node *node; + struct device_node *node, *overlay_node; struct fragment *fragment; struct fragment *fragments; int cnt, ret; + INIT_LIST_HEAD(&ovcs->ovcs_list); + + of_changeset_init(&ovcs->cset); + + ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL); + if (ovcs->id <= 0) + return ovcs->id; + cnt = 0; - for_each_child_of_node(tree, node) - cnt++; - if (of_get_child_by_name(tree, "__symbols__")) + /* fragment nodes */ + for_each_child_of_node(tree, node) { + overlay_node = of_get_child_by_name(node, "__overlay__"); + if (overlay_node) { + cnt++; + of_node_put(overlay_node); + } + } + + node = of_get_child_by_name(tree, "__symbols__"); + if (node) { cnt++; + of_node_put(node); + } fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL); - if (!fragments) - return -ENOMEM; + if (!fragments) { + ret = -ENOMEM; + goto err_free_idr; + } cnt = 0; for_each_child_of_node(tree, node) { - ret = of_fill_overlay_info(ovcs, node, &fragments[cnt]); - if (!ret) - cnt++; + fragment = &fragments[cnt]; + fragment->overlay = of_get_child_by_name(node, "__overlay__"); + if (fragment->overlay) { + fragment->target = find_target_node(node); + if (!fragment->target) { + of_node_put(fragment->overlay); + ret = -EINVAL; + goto err_free_fragments; + } else { + cnt++; + } + } } node = of_get_child_by_name(tree, "__symbols__"); @@ -466,44 +459,51 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, if (!fragment->target) { pr_err("no symbols in root of device tree.\n"); - return -EINVAL; + ret = -EINVAL; + goto err_free_fragments; } cnt++; } if (!cnt) { - kfree(fragments); - return -ENODEV; + ret = -EINVAL; + goto err_free_fragments; } ovcs->count = cnt; ovcs->fragments = fragments; return 0; + + +err_free_fragments: + kfree(fragments); +err_free_idr: + idr_remove(&ovcs_idr, ovcs->id); + + return ret; } -/** - * free_overlay_fragments() - Free a fragments array - * @ovcs Overlay to free the overlay info from - * - * Frees the memory of an ovcs->fragments[] array. - */ -static void free_overlay_fragments(struct overlay_changeset *ovcs) +static void free_overlay_changeset(struct overlay_changeset *ovcs) { int i; - /* do it in reverse */ - for (i = ovcs->count - 1; i >= 0; i--) { + if (!ovcs->cset.entries.next) + return; + of_changeset_destroy(&ovcs->cset); + + if (ovcs->id) + idr_remove(&ovcs_idr, ovcs->id); + + for (i = 0; i < ovcs->count; i++) { of_node_put(ovcs->fragments[i].target); of_node_put(ovcs->fragments[i].overlay); } - kfree(ovcs->fragments); -} -static LIST_HEAD(ovcs_list); -static DEFINE_IDR(ovcs_idr); + kfree(ovcs); +} /** * of_overlay_apply() - Create and apply an overlay changeset @@ -517,47 +517,34 @@ static void free_overlay_fragments(struct overlay_changeset *ovcs) int of_overlay_apply(struct device_node *tree) { struct overlay_changeset *ovcs; - int id, ret; + int ret; ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); if (!ovcs) return -ENOMEM; - ovcs->id = -1; - - INIT_LIST_HEAD(&ovcs->ovcs_list); - - of_changeset_init(&ovcs->cset); mutex_lock(&of_mutex); - id = idr_alloc(&ovcs_idr, ovcs, 0, 0, GFP_KERNEL); - if (id < 0) { - ret = id; - goto err_destroy_trans; - } - ovcs->id = id; - ret = init_overlay_changeset(ovcs, tree); if (ret) { - pr_err("init_overlay_changeset() failed for tree@%pOF\n", - tree); - goto err_free_idr; + pr_err("init_overlay_changeset() failed, ret = %d\n", ret); + goto err_free_overlay_changeset; } ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); if (ret < 0) { pr_err("%s: Pre-apply notifier failed (ret=%d)\n", __func__, ret); - goto err_free_overlay_fragments; + goto err_free_overlay_changeset; } ret = build_changeset(ovcs); if (ret) - goto err_free_overlay_fragments; + goto err_free_overlay_changeset; ret = __of_changeset_apply(&ovcs->cset); if (ret) - goto err_free_overlay_fragments; + goto err_free_overlay_changeset; list_add_tail(&ovcs->ovcs_list, &ovcs_list); @@ -565,15 +552,11 @@ int of_overlay_apply(struct device_node *tree) mutex_unlock(&of_mutex); - return id; + return ovcs->id; + +err_free_overlay_changeset: + free_overlay_changeset(ovcs); -err_free_overlay_fragments: - free_overlay_fragments(ovcs); -err_free_idr: - idr_remove(&ovcs_idr, ovcs->id); -err_destroy_trans: - of_changeset_destroy(&ovcs->cset); - kfree(ovcs); mutex_unlock(&of_mutex); return ret; @@ -684,13 +667,14 @@ int of_overlay_remove(int ovcs_id) } overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); + list_del(&ovcs->ovcs_list); + __of_changeset_revert(&ovcs->cset); + overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); - free_overlay_fragments(ovcs); - idr_remove(&ovcs_idr, ovcs_id); - of_changeset_destroy(&ovcs->cset); - kfree(ovcs); + + free_overlay_changeset(ovcs); out: mutex_unlock(&of_mutex); @@ -709,20 +693,15 @@ int of_overlay_remove(int ovcs_id) int of_overlay_remove_all(void) { struct overlay_changeset *ovcs, *ovcs_n; - - mutex_lock(&of_mutex); + int ret; /* the tail of list is guaranteed to be safe to remove */ list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) { - list_del(&ovcs->ovcs_list); - __of_changeset_revert(&ovcs->cset); - free_overlay_fragments(ovcs); - idr_remove(&ovcs_idr, ovcs->id); - kfree(ovcs); + ret = of_overlay_remove(ovcs->id); + if (ret) + return ret; } - mutex_unlock(&of_mutex); - return 0; } EXPORT_SYMBOL_GPL(of_overlay_remove_all); From patchwork Tue Oct 17 01:17:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826693 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="CMjx7WM3"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHRq58PWz9s82 for ; Tue, 17 Oct 2017 12:20:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754692AbdJQBTv (ORCPT ); Mon, 16 Oct 2017 21:19:51 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:45134 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756624AbdJQBSO (ORCPT ); Mon, 16 Oct 2017 21:18:14 -0400 Received: by mail-pf0-f194.google.com with SMTP id d28so127707pfe.2; Mon, 16 Oct 2017 18:18:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=E6R46yXRwr8IrzaKgIvsBck7lxcKxbNY6sYRcAdY7Xg=; b=CMjx7WM3oJ0C9o9KgYBeOwMA7czHbNwTCFMoNsjFDZ8+y7ZVWuP3q5Kn5umwmQ8Jc+ iJurldgoOIC+HLyKWkfpcvPh5JfmcngJtO/tsAmjCQwgKVEkHYbUzf49RVkK5MlSxziH 4GOBLofmLmJjpdE5tyg3U/sdzcOiL0RzgOzNPe3mBcE2D3mWJzF+bRDDqDCSZJR/T7Ck upCP0t009dGFnzputUoGjmqS7Adp0WynZmNSO6m/CSpD+EcfE9bDRgEVscMCGlG5Z2ib BKo/vv3hTBbayLkAyWae/LuhfTUBEHwSUlNwtiDgx8wB3OBJrbh27MmdD/+k4eAHXE1H IHRw== 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:in-reply-to :references; bh=E6R46yXRwr8IrzaKgIvsBck7lxcKxbNY6sYRcAdY7Xg=; b=cWR3L9qppoHAki6qGyWEA5mvp4ZgNw186/nBteXSnqIWyQyYYdL66LUpwx712wZYJw 9h5893DAc9jcoCC1f7Ewkl7wHUYGZ1kqchlVFyrLJig2RCee2FVhp3SVUG4maG0CbYRa NmMfiTKFXcgzMVnj6U4qv6Jeebc8nUk8erPkP3WXPjqqdYREcE79ucMLmmlmUZYNkl+S 0ZzKX56H/yBnc9Z6WBE5Fb2ixbYXBdUx3c/YeUofPR8hPuElDmAyUXOAKP0oKRC6scF1 sgdRZL2fmS9RjFZN2Bz7DYnCXFPDx0zPel3p/DrsRj5Uzi+s/Y+xHBk06B/LcPoyczUE tyIg== X-Gm-Message-State: AMCzsaV1iXnJ9qE9q3X8hqXXwbI7Q69vkp/2j0sKHwEhvtj0iDpXXzsG n5YXysqAWsseGpJextL+j9Y= X-Google-Smtp-Source: AOwi7QA04gjNrxvsO9uXqSh6mB06QyNqv27deR69XSqAZE4MBBJ4CzjrnRQXBAF4Nbb3EA6TWVr9EQ== X-Received: by 10.159.194.6 with SMTP id x6mr10584288pln.359.1508203093617; Mon, 16 Oct 2017 18:18:13 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:12 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 06/12] of: overlay: detect cases where device tree may become corrupt Date: Mon, 16 Oct 2017 18:17:48 -0700 Message-Id: <1508203074-26917-7-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand When an attempt to apply an overlay changeset fails, an effort is made to revert any partial application of the changeset. When an attempt to remove an overlay changeset fails, an effort is made to re-apply any partial reversion of the changeset. The existing code does not check for failure to recover a failed overlay changeset application or overlay changeset revert. Add the missing checks and flag the devicetree as corrupt if the state of the devicetree can not be determined. Improve and expand the returned errors to more fully reflect the result of the effort to undo the partial effects of a failed attempt to apply or remove an overlay changeset. If the device tree might be corrupt, do not allow further attempts to apply or remove an overlay changeset. When creating an overlay changeset from an overlay device tree, add some additional warnings if the state of the overlay device tree is not as expected. Signed-off-by: Frank Rowand --- drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 5 +- drivers/of/dynamic.c | 135 +++++++++++--- drivers/of/of_private.h | 8 +- drivers/of/overlay.c | 253 ++++++++++++++++++++++----- drivers/of/unittest.c | 57 +++--- include/linux/of.h | 10 +- 6 files changed, 372 insertions(+), 96 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 5f5b7ba35f1d..7a7be0515bfd 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -204,7 +204,7 @@ static void __init tilcdc_convert_slave_node(void) /* For all memory needed for the overlay tree. This memory can be freed after the overlay has been applied. */ struct kfree_table kft; - int ret; + int ovcs_id, ret; if (kfree_table_init(&kft)) return; @@ -247,7 +247,8 @@ static void __init tilcdc_convert_slave_node(void) tilcdc_node_disable(slave); - ret = of_overlay_apply(overlay); + ovcs_id = 0; + ret = of_overlay_apply(overlay, &ovcs_id); if (ret) pr_err("%s: Applying overlay changeset failed: %d\n", __func__, ret); diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 124510d56421..c1026efd6f9e 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -508,11 +508,12 @@ static void __of_changeset_entry_invert(struct of_changeset_entry *ce, } } -static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) +static int __of_changeset_entry_notify(struct of_changeset_entry *ce, + bool revert) { struct of_reconfig_data rd; struct of_changeset_entry ce_inverted; - int ret; + int ret = 0; if (revert) { __of_changeset_entry_invert(ce, &ce_inverted); @@ -534,11 +535,12 @@ static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool reve default: pr_err("invalid devicetree changeset action: %i\n", (int)ce->action); - return; + ret = -EINVAL; } if (ret) pr_err("changeset notifier error @%pOF\n", ce->np); + return ret; } static int __of_changeset_entry_apply(struct of_changeset_entry *ce) @@ -672,32 +674,82 @@ void of_changeset_destroy(struct of_changeset *ocs) } EXPORT_SYMBOL_GPL(of_changeset_destroy); -int __of_changeset_apply(struct of_changeset *ocs) +/* + * Apply the changeset entries in @ocs. + * If apply fails, an attempt is made to revert the entries that were + * successfully applied. + * + * If multiple revert errors occur then only the final revert error is reported. + * + * Returns 0 on success, a negative error value in case of an error. + * If a revert error occurs, it is returned in *ret_revert. + */ +int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert) { struct of_changeset_entry *ce; - int ret; + int ret, ret_tmp; - /* perform the rest of the work */ pr_debug("changeset: applying...\n"); list_for_each_entry(ce, &ocs->entries, node) { ret = __of_changeset_entry_apply(ce); if (ret) { pr_err("Error applying changeset (%d)\n", ret); - list_for_each_entry_continue_reverse(ce, &ocs->entries, node) - __of_changeset_entry_revert(ce); + list_for_each_entry_continue_reverse(ce, &ocs->entries, + node) { + ret_tmp = __of_changeset_entry_revert(ce); + if (ret_tmp) + *ret_revert = ret_tmp; + } return ret; } } - pr_debug("changeset: applied, emitting notifiers.\n"); + + return 0; +} + +/* + * Returns 0 on success, a negative error value in case of an error. + * + * If multiple changset entry notification errors occur then only the + * final notification error is reported. + */ +int __of_changeset_apply_notify(struct of_changeset *ocs) +{ + struct of_changeset_entry *ce; + int ret = 0, ret_tmp; + + pr_debug("changeset: emitting notifiers.\n"); /* drop the global lock while emitting notifiers */ mutex_unlock(&of_mutex); - list_for_each_entry(ce, &ocs->entries, node) - __of_changeset_entry_notify(ce, 0); + list_for_each_entry(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_notify(ce, 0); + if (ret_tmp) + ret = ret_tmp; + } mutex_lock(&of_mutex); pr_debug("changeset: notifiers sent.\n"); - return 0; + return ret; +} + +/* + * Returns 0 on success, a negative error value in case of an error. + * + * If a changeset entry apply fails, an attempt is made to revert any + * previous entries in the changeset. If any of the reverts fails, + * that failure is not reported. Thus the state of the device tree + * is unknown if an apply error occurs. + */ +static int __of_changeset_apply(struct of_changeset *ocs) +{ + int ret, ret_revert = 0; + + ret = __of_changeset_apply_entries(ocs, &ret_revert); + if (!ret) + ret = __of_changeset_apply_notify(ocs); + + return ret; } /** @@ -724,31 +776,74 @@ int of_changeset_apply(struct of_changeset *ocs) } EXPORT_SYMBOL_GPL(of_changeset_apply); -int __of_changeset_revert(struct of_changeset *ocs) +/* + * Revert the changeset entries in @ocs. + * If revert fails, an attempt is made to re-apply the entries that were + * successfully removed. + * + * If multiple re-apply errors occur then only the final apply error is + * reported. + * + * Returns 0 on success, a negative error value in case of an error. + * If an apply error occurs, it is returned in *ret_apply. + */ +int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply) { struct of_changeset_entry *ce; - int ret; + int ret, ret_tmp; pr_debug("changeset: reverting...\n"); list_for_each_entry_reverse(ce, &ocs->entries, node) { ret = __of_changeset_entry_revert(ce); if (ret) { pr_err("Error reverting changeset (%d)\n", ret); - list_for_each_entry_continue(ce, &ocs->entries, node) - __of_changeset_entry_apply(ce); + list_for_each_entry_continue(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_apply(ce); + if (ret_tmp) + *ret_apply = ret_tmp; + } return ret; } } - pr_debug("changeset: reverted, emitting notifiers.\n"); + + return 0; +} + +/* + * If multiple changset entry notification errors occur then only the + * final notification error is reported. + */ +int __of_changeset_revert_notify(struct of_changeset *ocs) +{ + struct of_changeset_entry *ce; + int ret = 0, ret_tmp; + + pr_debug("changeset: emitting notifiers.\n"); /* drop the global lock while emitting notifiers */ mutex_unlock(&of_mutex); - list_for_each_entry_reverse(ce, &ocs->entries, node) - __of_changeset_entry_notify(ce, 1); + list_for_each_entry_reverse(ce, &ocs->entries, node) { + ret_tmp = __of_changeset_entry_notify(ce, 1); + if (ret_tmp) + ret = ret_tmp; + } mutex_lock(&of_mutex); pr_debug("changeset: notifiers sent.\n"); - return 0; + return ret; +} + +static int __of_changeset_revert(struct of_changeset *ocs) +{ + int ret, ret_reply; + + ret_reply = 0; + ret = __of_changeset_revert_entries(ocs, &ret_reply); + + if (!ret) + ret = __of_changeset_revert_notify(ocs); + + return ret; } /** diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 3ae12ffbf547..b66e8a812147 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -45,8 +45,12 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj) extern int of_property_notify(int action, struct device_node *np, struct property *prop, struct property *old_prop); extern void of_node_release(struct kobject *kobj); -extern int __of_changeset_apply(struct of_changeset *ocs); -extern int __of_changeset_revert(struct of_changeset *ocs); +extern int __of_changeset_apply_entries(struct of_changeset *ocs, + int *ret_revert); +extern int __of_changeset_apply_notify(struct of_changeset *ocs); +extern int __of_changeset_revert_entries(struct of_changeset *ocs, + int *ret_apply); +extern int __of_changeset_revert_notify(struct of_changeset *ocs); #else /* CONFIG_OF_DYNAMIC */ static inline int of_property_notify(int action, struct device_node *np, struct property *prop, struct property *old_prop) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 0f92a5c26748..c7526186b1c8 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -50,6 +50,22 @@ struct overlay_changeset { struct of_changeset cset; }; +/* flags are sticky - once set, do not reset */ +static int devicetree_state_flags; +#define DTSF_APPLY_FAIL 0x01 +#define DTSF_REVERT_FAIL 0x02 + +/* + * If a changeset apply or revert encounters an error, an attempt will + * be made to undo partial changes, but may fail. If the undo fails + * we do not know the state of the devicetree. + */ +static int devicetree_corrupt(void) +{ + return devicetree_state_flags & + (DTSF_APPLY_FAIL | DTSF_REVERT_FAIL); +} + static int build_changeset_next_level(struct overlay_changeset *ovcs, struct device_node *target_node, const struct device_node *overlay_node, @@ -72,6 +88,13 @@ int of_overlay_notifier_unregister(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister); +static char *of_overlay_action_name[] = { + "pre-apply", + "post-apply", + "pre-remove", + "post-remove", +}; + static int overlay_notify(struct overlay_changeset *ovcs, enum of_overlay_notify_action action) { @@ -86,8 +109,14 @@ static int overlay_notify(struct overlay_changeset *ovcs, ret = blocking_notifier_call_chain(&overlay_notify_chain, action, &nd); - if (ret) - return notifier_to_errno(ret); + if (ret == NOTIFY_STOP) + return 0; + if (ret) { + ret = notifier_to_errno(ret); + pr_err("overlay changeset %s notifier error %d, target: %pOF\n", + of_overlay_action_name[action], ret, nd.target); + return ret; + } } return 0; @@ -231,6 +260,14 @@ static int add_changeset_property(struct overlay_changeset *ovcs, * build_changeset_next_level(). * * NOTE: Multiple mods of created nodes not supported. + * If more than one fragment contains a node that does not already exist + * in the live tree, then for each fragment of_changeset_attach_node() + * will add a changeset entry to add the node. When the changeset is + * applied, __of_attach_node() will attach the node twice (once for + * each fragment). At this point the device tree will be corrupted. + * + * TODO: add integrity check to ensure that multiple fragments do not + * create the same node. * * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if * invalid @overlay. @@ -303,8 +340,8 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, ret = add_changeset_property(ovcs, target_node, prop, is_symbols_node); if (ret) { - pr_err("Failed to apply prop @%pOF/%s\n", - target_node, prop->name); + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", + target_node, prop->name, ret); return ret; } } @@ -315,8 +352,8 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, for_each_child_of_node(overlay_node, child) { ret = add_changeset_node(ovcs, target_node, child); if (ret) { - pr_err("Failed to apply node @%pOF/%s\n", - target_node, child->name); + pr_debug("Failed to apply node @%pOF/%s, err=%d\n", + target_node, child->name, ret); of_node_put(child); return ret; } @@ -348,7 +385,7 @@ static int build_changeset(struct overlay_changeset *ovcs) fragment->overlay, fragment->is_symbols_node); if (ret) { - pr_err("apply failed '%pOF'\n", fragment->target); + pr_debug("apply failed '%pOF'\n", fragment->target); return ret; } } @@ -403,6 +440,19 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, struct fragment *fragments; int cnt, ret; + /* + * Warn for some issues. Can not return -EINVAL for these until + * of_unittest_apply_overlay() is fixed to pass these checks. + */ + if (!of_node_check_flag(tree, OF_DYNAMIC)) + pr_debug("%s() tree is not dynamic\n", __func__); + + if (!of_node_check_flag(tree, OF_DETACHED)) + pr_debug("%s() tree is not detached\n", __func__); + + if (!of_node_is_root(tree)) + pr_debug("%s() tree is not root\n", __func__); + INIT_LIST_HEAD(&ovcs->ovcs_list); of_changeset_init(&ovcs->cset); @@ -476,12 +526,13 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, return 0; - err_free_fragments: kfree(fragments); err_free_idr: idr_remove(&ovcs_idr, ovcs->id); + pr_err("%s() failed, ret = %d\n", __func__, ret); + return ret; } @@ -508,33 +559,71 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs) /** * of_overlay_apply() - Create and apply an overlay changeset * @tree: Expanded overlay device tree + * @ovcs_id: Pointer to overlay changeset id + * + * Creates and applies an overlay changeset. * - * Creates and applies an overlay changeset. If successful, the overlay - * changeset is added to the overlay changeset list. + * If an error occurs in a pre-apply notifier, then no changes are made + * to the device tree. * - * Returns the id of the created overlay changeset, or a negative error number + + * A non-zero return value will not have created the changeset if error is from: + * - parameter checks + * - building the changeset + * - overlay changset pre-apply notifier + * + * If an error is returned by an overlay changeset pre-apply notifier + * then no further overlay changeset pre-apply notifier will be called. + * + * A non-zero return value will have created the changeset if error is from: + * - overlay changeset entry notifier + * - overlay changset post-apply notifier + * + * If an error is returned by an overlay changeset post-apply notifier + * then no further overlay changeset post-apply notifier will be called. + * + * If more than one notifier returns an error, then the last notifier + * error to occur is returned. + * + * If an error occurred while applying the overlay changeset, then an + * attempt is made to revert any changes that were made to the + * device tree. If there were any errors during the revert attempt + * then the state of the device tree can not be determined, and any + * following attempt to apply or remove an overlay changeset will be + * refused. + * + * Returns 0 on success, or a negative error number. Overlay changeset + * id is returned to *ovcs_id. */ -int of_overlay_apply(struct device_node *tree) + +int of_overlay_apply(struct device_node *tree, int *ovcs_id) { struct overlay_changeset *ovcs; - int ret; + int ret = 0, ret_revert, ret_tmp; + + *ovcs_id = 0; + + if (devicetree_corrupt()) { + pr_err("devicetree state suspect, refuse to apply overlay\n"); + ret = -EBUSY; + goto out; + } ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); - if (!ovcs) - return -ENOMEM; + if (!ovcs) { + ret = -ENOMEM; + goto out; + } mutex_lock(&of_mutex); ret = init_overlay_changeset(ovcs, tree); - if (ret) { - pr_err("init_overlay_changeset() failed, ret = %d\n", ret); + if (ret) goto err_free_overlay_changeset; - } ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); - if (ret < 0) { - pr_err("%s: Pre-apply notifier failed (ret=%d)\n", - __func__, ret); + if (ret) { + pr_err("overlay changeset pre-apply notify error %d\n", ret); goto err_free_overlay_changeset; } @@ -542,23 +631,46 @@ int of_overlay_apply(struct device_node *tree) if (ret) goto err_free_overlay_changeset; - ret = __of_changeset_apply(&ovcs->cset); - if (ret) + ret_revert = 0; + ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert); + if (ret) { + if (ret_revert) { + pr_debug("overlay changeset revert error %d\n", + ret_revert); + devicetree_state_flags |= DTSF_APPLY_FAIL; + } goto err_free_overlay_changeset; + } else { + ret = __of_changeset_apply_notify(&ovcs->cset); + if (ret) + pr_err("overlay changeset entry notify error %d\n", + ret); + /* fall through */ + } list_add_tail(&ovcs->ovcs_list, &ovcs_list); - - overlay_notify(ovcs, OF_OVERLAY_POST_APPLY); + *ovcs_id = ovcs->id; + + ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY); + if (ret_tmp) { + pr_err("overlay changeset post-apply notify error %d\n", + ret_tmp); + if (!ret) + ret = ret_tmp; + } mutex_unlock(&of_mutex); - return ovcs->id; + goto out; err_free_overlay_changeset: free_overlay_changeset(ovcs); mutex_unlock(&of_mutex); +out: + pr_debug("%s() err=%d\n", __func__, ret); + return ret; } EXPORT_SYMBOL_GPL(of_overlay_apply); @@ -640,45 +752,106 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) /** * of_overlay_remove() - Revert and free an overlay changeset - * @ovcs_id: Overlay changeset id number + * @ovcs_id: Pointer to overlay changeset id * - * Removes an overlay if it is permissible. ovcs_id was previously returned + * Removes an overlay if it is permissible. @ovcs_id was previously returned * by of_overlay_apply(). * - * Returns 0 on success, or a negative error number + * If an error occurred while attempting to revert the overlay changeset, + * then an attempt is made to re-apply any changeset entry that was + * reverted. If an error occurs on re-apply then the state of the device + * tree can not be determined, and any following attempt to apply or remove + * an overlay changeset will be refused. + * + * A non-zero return value will not revert the changeset if error is from: + * - parameter checks + * - overlay changset pre-remove notifier + * - overlay changeset entry revert + * + * If an error is returned by an overlay changeset pre-remove notifier + * then no further overlay changeset pre-remove notifier will be called. + * + * If more than one notifier returns an error, then the last notifier + * error to occur is returned. + * + * A non-zero return value will revert the changeset if error is from: + * - overlay changeset entry notifier + * - overlay changset post-remove notifier + * + * If an error is returned by an overlay changeset post-remove notifier + * then no further overlay changeset post-remove notifier will be called. + * + * Returns 0 on success, or a negative error number. *ovcs_id is set to + * zero after reverting the changeset, even if a subsequent error occurs. */ -int of_overlay_remove(int ovcs_id) +int of_overlay_remove(int *ovcs_id) { struct overlay_changeset *ovcs; - int ret = 0; + int ret, ret_apply, ret_tmp; + + ret = 0; + + if (devicetree_corrupt()) { + pr_err("suspect devicetree state, refuse to remove overlay\n"); + ret = -EBUSY; + goto out; + } mutex_lock(&of_mutex); - ovcs = idr_find(&ovcs_idr, ovcs_id); + ovcs = idr_find(&ovcs_idr, *ovcs_id); if (!ovcs) { ret = -ENODEV; - pr_err("remove: Could not find overlay #%d\n", ovcs_id); - goto out; + pr_err("remove: Could not find overlay #%d\n", *ovcs_id); + goto out_unlock; } if (!overlay_removal_is_ok(ovcs)) { ret = -EBUSY; - goto out; + goto out_unlock; } - overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); + ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); + if (ret) { + pr_err("overlay changeset pre-remove notify error %d\n", ret); + goto out_unlock; + } list_del(&ovcs->ovcs_list); - __of_changeset_revert(&ovcs->cset); + ret_apply = 0; + ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply); + if (ret) { + if (ret_apply) + devicetree_state_flags |= DTSF_REVERT_FAIL; + goto out_unlock; + } else { + ret = __of_changeset_revert_notify(&ovcs->cset); + if (ret) { + pr_err("overlay changeset entry notify error %d\n", + ret); + /* fall through - changeset was reverted */ + } + } - overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); + *ovcs_id = 0; + + ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); + if (ret_tmp) { + pr_err("overlay changeset post-remove notify error %d\n", + ret_tmp); + if (!ret) + ret = ret_tmp; + } free_overlay_changeset(ovcs); -out: +out_unlock: mutex_unlock(&of_mutex); +out: + pr_debug("%s() err=%d\n", __func__, ret); + return ret; } EXPORT_SYMBOL_GPL(of_overlay_remove); @@ -697,7 +870,7 @@ int of_overlay_remove_all(void) /* the tail of list is guaranteed to be safe to remove */ list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) { - ret = of_overlay_remove(ovcs->id); + ret = of_overlay_remove(&ovcs->id); if (ret) return ret; } diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index e19dcd80e7a7..db2f170186de 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1218,7 +1218,7 @@ static void of_unittest_untrack_overlay(int id) static void of_unittest_destroy_tracked_overlays(void) { - int id, ret, defers; + int id, ret, defers, ovcs_id; if (overlay_first_id < 0) return; @@ -1231,7 +1231,8 @@ static void of_unittest_destroy_tracked_overlays(void) if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id))) continue; - ret = of_overlay_remove(id + overlay_first_id); + ovcs_id = id + overlay_first_id; + ret = of_overlay_remove(&ovcs_id); if (ret == -ENODEV) { pr_warn("%s: no overlay to destroy for #%d\n", __func__, id + overlay_first_id); @@ -1253,7 +1254,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, int *overlay_id) { struct device_node *np = NULL; - int ret, id = -1; + int ret; np = of_find_node_by_path(overlay_path(overlay_nr)); if (np == NULL) { @@ -1263,23 +1264,20 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, goto out; } - ret = of_overlay_apply(np); + *overlay_id = 0; + ret = of_overlay_apply(np, overlay_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr)); goto out; } - id = ret; - of_unittest_track_overlay(id); + of_unittest_track_overlay(*overlay_id); ret = 0; out: of_node_put(np); - if (overlay_id) - *overlay_id = id; - return ret; } @@ -1287,7 +1285,7 @@ static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr, static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, int before, int after, enum overlay_type ovtype) { - int ret; + int ret, ovcs_id; /* unittest device must not be in before state */ if (of_unittest_device_exists(unittest_nr, ovtype) != before) { @@ -1298,7 +1296,8 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, return -EINVAL; } - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, NULL); + ovcs_id = 0; + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); if (ret != 0) { /* of_unittest_apply_overlay already called unittest() */ return ret; @@ -1321,7 +1320,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, int unittest_nr, int before, int after, enum overlay_type ovtype) { - int ret, ov_id; + int ret, ovcs_id; /* unittest device must be in before state */ if (of_unittest_device_exists(unittest_nr, ovtype) != before) { @@ -1333,7 +1332,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, } /* apply the overlay */ - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ov_id); + ovcs_id = 0; + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); if (ret != 0) { /* of_unittest_apply_overlay already called unittest() */ return ret; @@ -1348,7 +1348,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr, return -EINVAL; } - ret = of_overlay_remove(ov_id); + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", overlay_path(overlay_nr), @@ -1450,7 +1450,7 @@ static void of_unittest_overlay_5(void) static void of_unittest_overlay_6(void) { struct device_node *np; - int ret, i, ov_id[2]; + int ret, i, ov_id[2], ovcs_id; int overlay_nr = 6, unittest_nr = 6; int before = 0, after = 1; @@ -1477,13 +1477,14 @@ static void of_unittest_overlay_6(void) return; } - ret = of_overlay_apply(np); + ovcs_id = 0; + ret = of_overlay_apply(np, &ovcs_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } - ov_id[i] = ret; + ov_id[i] = ovcs_id; of_unittest_track_overlay(ov_id[i]); } @@ -1501,7 +1502,8 @@ static void of_unittest_overlay_6(void) } for (i = 1; i >= 0; i--) { - ret = of_overlay_remove(ov_id[i]); + ovcs_id = ov_id[i]; + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", overlay_path(overlay_nr + i), @@ -1532,7 +1534,7 @@ static void of_unittest_overlay_6(void) static void of_unittest_overlay_8(void) { struct device_node *np; - int ret, i, ov_id[2]; + int ret, i, ov_id[2], ovcs_id; int overlay_nr = 8, unittest_nr = 8; /* we don't care about device state in this test */ @@ -1547,18 +1549,20 @@ static void of_unittest_overlay_8(void) return; } - ret = of_overlay_apply(np); + ovcs_id = 0; + ret = of_overlay_apply(np, &ovcs_id); if (ret < 0) { unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } - ov_id[i] = ret; + ov_id[i] = ovcs_id; of_unittest_track_overlay(ov_id[i]); } /* now try to remove first overlay (it should fail) */ - ret = of_overlay_remove(ov_id[0]); + ovcs_id = ov_id[0]; + ret = of_overlay_remove(&ovcs_id); if (ret == 0) { unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", overlay_path(overlay_nr + 0), @@ -1569,7 +1573,8 @@ static void of_unittest_overlay_8(void) /* removing them in order should work */ for (i = 1; i >= 0; i--) { - ret = of_overlay_remove(ov_id[i]); + ovcs_id = ov_id[i]; + ret = of_overlay_remove(&ovcs_id); if (ret != 0) { unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", overlay_path(overlay_nr + i), @@ -2151,13 +2156,11 @@ static int __init overlay_data_add(int onum) goto out_free_np_overlay; } - ret = of_overlay_apply(info->np_overlay); + info->overlay_id = 0; + ret = of_overlay_apply(info->np_overlay, &info->overlay_id); if (ret < 0) { pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); goto out_free_np_overlay; - } else { - info->overlay_id = ret; - ret = 0; } pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); diff --git a/include/linux/of.h b/include/linux/of.h index 45e787e28ce7..49e5f24fb390 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1292,7 +1292,7 @@ static inline bool of_device_is_system_power_controller(const struct device_node */ enum of_overlay_notify_action { - OF_OVERLAY_PRE_APPLY, + OF_OVERLAY_PRE_APPLY = 0, OF_OVERLAY_POST_APPLY, OF_OVERLAY_PRE_REMOVE, OF_OVERLAY_POST_REMOVE, @@ -1306,8 +1306,8 @@ struct of_overlay_notify_data { #ifdef CONFIG_OF_OVERLAY /* ID based overlays; the API for external users */ -int of_overlay_apply(struct device_node *tree); -int of_overlay_remove(int id); +int of_overlay_apply(struct device_node *tree, int *ovcs_id); +int of_overlay_remove(int *ovcs_id); int of_overlay_remove_all(void); int of_overlay_notifier_register(struct notifier_block *nb); @@ -1315,12 +1315,12 @@ struct of_overlay_notify_data { #else -static inline int of_overlay_apply(struct device_node *tree) +static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id) { return -ENOTSUPP; } -static inline int of_overlay_remove(int id) +static inline int of_overlay_remove(int *ovcs_id) { return -ENOTSUPP; } From patchwork Tue Oct 17 01:17:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826691 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jisi42HN"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHR85MsBz9sPk for ; Tue, 17 Oct 2017 12:19:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757663AbdJQBSR (ORCPT ); Mon, 16 Oct 2017 21:18:17 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:50112 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754063AbdJQBSP (ORCPT ); Mon, 16 Oct 2017 21:18:15 -0400 Received: by mail-pf0-f195.google.com with SMTP id i5so119979pfe.6; Mon, 16 Oct 2017 18:18:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cvaQEQDg3A1vcMMvRHTCyjivZ3Yd86XbWm749CXkCA4=; b=jisi42HNj6wD1BuzM83o9/YIJY5inhyNQmMZn9B1/kv/AIq+Pl3g5ah+U8T4Mz2+7e AgMNSQ1tRGe7KGPzoromQOlc48AV9bWLeHgHiGw4lYW6xEz2eBIYCD+90iMyvx4lHceR oE7MtmEScXHnC1d01cVhWza4VtoevRAQMg9uYQ15k0Lpo9L/U461C52GVdtX3mWnafBN pDsYMsqxBeKEBWq9tyN2SxCWoGz+HEcENX0DNsG1Jc/bda84h8A3VKEC0IeS9SdIW7Na wIS4AyvEOt5pt9QZFRGod+9rAVxk/5BE40tAFnbVZFjRihlGqaLtfkySS5CKMP2pKgJ6 yUtQ== 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:in-reply-to :references; bh=cvaQEQDg3A1vcMMvRHTCyjivZ3Yd86XbWm749CXkCA4=; b=iviOO5qsVhRsu8u2WUzQSuzuUfpLPb++KJM92zLyNrYs+Kwbr7B6s0/qXjhEyYVQIU SEkFHZxjzVUn2smncDnddtv1g+cWfP5WoN9s+NX8DSImng29tsJ8mdAsVf+PBXoJwY4T sIVwXPyUktKh7MWeKNw9iGLVuxsETc/D8NBHzBpKehBefHItXgrAeCyBlJyW4e4fL8Yk rvlSPNnmMFoY83qQbBbwtJdudLW8V0M+ED3PffHOYnQxNBxs33174vzZ6VzgqzTuZy5K dfWMPrRu40NbcMfIKO/HYtCpjA+zRvz8ubmnAaR2+KMNEq4jGpetnGcSunPOj6ow4Ph5 k7Yg== X-Gm-Message-State: AMCzsaVn50MISZGdgcuhV0HWMzED5+Jk9grQE6q7vHfE/jOq20+kpoas L+uJKoCpl/nxY7MhiJauAaU= X-Google-Smtp-Source: AOwi7QAbP6mqRbNL4Z4MhCUu1Nczi7Dt7W4p8KXUHk+A3yxJKjCT7rPdEu6N0qr0i8lWE0oO6OsEGg== X-Received: by 10.84.135.129 with SMTP id 1mr10774132plj.47.1508203095056; Mon, 16 Oct 2017 18:18:15 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:14 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 07/12] of: overlay: expand check of whether overlay changeset can be removed Date: Mon, 16 Oct 2017 18:17:49 -0700 Message-Id: <1508203074-26917-8-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand The test of whether it is safe to remove an overlay changeset looked at whether any node in the overlay changeset was in a subtree rooted at any more recently applied overlay changeset node. The test failed to determine whether any node in the overlay changeset was the root of a subtree that contained a more recently applied overlay changeset node. Add this additional check to the test. The test is still lacking any check for any phandle dependencies. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index c7526186b1c8..015d8b112f60 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -698,13 +698,13 @@ static int find_node(struct device_node *tree, struct device_node *np) } /* - * Is @remove_ce_np a child of or the same as any + * Is @remove_ce_node a child of, a parent of, or the same as any * node in an overlay changeset more topmost than @remove_ovcs? * * Returns 1 if found, else 0 */ -static int node_in_later_cs(struct overlay_changeset *remove_ovcs, - struct device_node *remove_ce_np) +static int node_overlaps_later_cs(struct overlay_changeset *remove_ovcs, + struct device_node *remove_ce_node) { struct overlay_changeset *ovcs; struct of_changeset_entry *ce; @@ -714,10 +714,16 @@ static int node_in_later_cs(struct overlay_changeset *remove_ovcs, break; list_for_each_entry(ce, &ovcs->cset.entries, node) { - if (find_node(ce->np, remove_ce_np)) { - pr_err("%s: #%d clashes #%d @%pOF\n", + if (find_node(ce->np, remove_ce_node)) { + pr_err("%s: #%d overlaps with #%d @%pOF\n", __func__, remove_ovcs->id, ovcs->id, - remove_ce_np); + remove_ce_node); + return 1; + } + if (find_node(remove_ce_node, ce->np)) { + pr_err("%s: #%d overlaps with #%d @%pOF\n", + __func__, remove_ovcs->id, ovcs->id, + remove_ce_node); return 1; } } @@ -741,7 +747,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) struct of_changeset_entry *remove_ce; list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) { - if (node_in_later_cs(remove_ovcs, remove_ce->np)) { + if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) { pr_err("overlay #%d is not topmost\n", remove_ovcs->id); return 0; } From patchwork Tue Oct 17 01:17:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826692 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tmof6Mly"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHRP3LZxz9sPk for ; Tue, 17 Oct 2017 12:19:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756517AbdJQBTc (ORCPT ); Mon, 16 Oct 2017 21:19:32 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:46217 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757598AbdJQBSQ (ORCPT ); Mon, 16 Oct 2017 21:18:16 -0400 Received: by mail-pg0-f65.google.com with SMTP id k7so129977pga.3; Mon, 16 Oct 2017 18:18:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YLBs9kKTG/GLWDQs8ny3/KYzFoAw8uGrObGOT1/hEeM=; b=tmof6Mly9UvqM/2LCF7o/T21dGY8h0Rv5UXP5ZDg9e1YVuNS47DjMMjjRR+SvGk9gh hnZK+PnfeQ1PPNFt2yGh9nl7vxKc/CSimHOhV1k7MubHctTeOczp6GfF1PeJMsT5xiW2 GZe+QDBF2sS7P4MrWGjLxG1idvpyfigkF8DtKIOPpAPCh+nkzBor9GzWFrIjIeybavF0 15GBjp0Z3Fi6TfBxUECvatwaOH07Cs4GGayJEoVYfXs4YYIniROo7JbGhPzujNEv8AFS oPiad1EEXflxo0SAtCUMd/rfZMO1mcgCQXKhv7z2d0cc7D2/RAMdL9E0H1sdZecA5ZLP f1bA== 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:in-reply-to :references; bh=YLBs9kKTG/GLWDQs8ny3/KYzFoAw8uGrObGOT1/hEeM=; b=fC3p5Sjc4VoOKXkIh33ikb4fBxjgVKQrho1D3uUkeX1cwYkWaklOrQInvY+C5QHpM0 XRMFkOCEilgSCk37ZwXtGneiniwyWv0RYqIHGDI6yg1StyY8b1fWkeS5XibyX4QgJgPR VtKCz4vrBvHzv7uCP3ncRU3+/DD5A6kdQKnxdirOgVyeDnjijymovVLYpwo8YI8V+IMu cvU5Tmmi+Fx/ievLei+7Lh5aR66NQBV1vxzD5j6MEQSpGIsuG0ZoZgFVj5HofA4jeiL4 dTeUjS4OlUetIeCDbrYTMp0fFWYsfTt/Mc6Yk2cY4sNQWYsz0HIRrMIBwIOSmEau47RN kk1g== X-Gm-Message-State: AMCzsaVuzqIyCOiDUqAtst1bQHembOnvq09UxHxJEU46YO3kCb7qnJ3R vwVgt8Lnm689KY0UbLPMo7M= X-Google-Smtp-Source: AOwi7QC8G/MjThKAqXMFVc2/Cc7ZUdhHOAhbsIDsPwH5pDALJj/wEeWH7rw71laq3nqTqLygy7yJZQ== X-Received: by 10.84.176.163 with SMTP id v32mr10663247plb.175.1508203096447; Mon, 16 Oct 2017 18:18:16 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:15 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 08/12] of: overlay: loosen overly strict phandle clash check Date: Mon, 16 Oct 2017 18:17:50 -0700 Message-Id: <1508203074-26917-9-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand When an overlay contains a node that already exists in the live device tree, the overlay node is not allowed to change the phandle of the existing node. The existing check refused to allow an overlay node to set the node phandle even when the existing node did not have a phandle. Relax the check to allow an overlay node to set the phandle value if the existing node does not have a phandle. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 015d8b112f60..a0d3222febdc 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -302,10 +302,10 @@ static int add_changeset_node(struct overlay_changeset *ovcs, return build_changeset_next_level(ovcs, tchild, node, 0); } - if (node->phandle) - return -EINVAL; - - ret = build_changeset_next_level(ovcs, tchild, node, 0); + if (node->phandle && tchild->phandle) + ret = -EINVAL; + else + ret = build_changeset_next_level(ovcs, tchild, node, 0); of_node_put(tchild); return ret; From patchwork Tue Oct 17 01:17:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826689 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="f0lxBh1z"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHQv31JZz9sPk for ; Tue, 17 Oct 2017 12:19:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758374AbdJQBS4 (ORCPT ); Mon, 16 Oct 2017 21:18:56 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:54386 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757672AbdJQBSS (ORCPT ); Mon, 16 Oct 2017 21:18:18 -0400 Received: by mail-pg0-f68.google.com with SMTP id l24so115825pgu.11; Mon, 16 Oct 2017 18:18:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=itDDbf99PdYlS6TkRUhuPteBe7rfJn3Yy/41d9M9/Lo=; b=f0lxBh1zG7z9B3fRxujJqiSo0G7HtR7JzsP2Efk/Kls0zoGbx+LkKLMqAoHS1EQQHl cTAoF83kx7kZ8TemQvenA4i2af283eON1ajHcSeWTbTKcANXX5w6xDNLvUBvtpvLkEsO 4GHcc+eqTVPGK45EYrJcjJU7AQY5uVMHeOTRRMSYzmxYUbUOxn0NFF11KUlZ2UIG1o3x kDEnKFqVTTvi5VJQOyBdJ4hfgbKwPZ4VJVtOU7xZVgvD1U9bYLy+XOmzBEqNcZuqa3D9 dLip7x3tVF38OpevH4eazAP0fxbLVZFhSFvLKyI+87oZUA9AlMF8szOX3ohuBfs62tAR f6rQ== 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:in-reply-to :references; bh=itDDbf99PdYlS6TkRUhuPteBe7rfJn3Yy/41d9M9/Lo=; b=Gc+hw+9ladUpu2JsdeCiqpRm0So19ozTSTf6gv267QpruZsvmvQb132AFPEoQfmd5B R39a3PkKQd8OLp12If2PuxwtHuT1soUoaNLnusAPxf7b4Gul/nHkE2KNGT+BhDsFWnxG niAMl+S1X3pEvthMRib5BpQGTzFln3nlZjIEXrWvAFl0GM96P0DHosq9Snz7I1RiqnFE 9GbG+K5R6qS/iUG4cM3wGICUQqG1wZ4/XESb9QKKFFyK5Mg9Pq7cvIFN9qp/Ngo9cJLK GIBCwgXxaBmkDTUuvPfqPuLVZLsiVUMA4427MBKLj5XgPIaWahfECu6o0goczsCu2GO4 AlpQ== X-Gm-Message-State: AMCzsaX/b5Wf7wRl4qvfNUuD10BtgitSM6+O1SUThIArGCQ6I7fK8OQI 9H+5uDjUQ0D1GQIdIFK5bk4= X-Google-Smtp-Source: AOwi7QC+oSiS84m9k7xT3a0J1MVVVrJXIsTLkVXWMNH0ZLxC4IPz5xvmcOl4lSlY+MBFF/WFizjV6Q== X-Received: by 10.159.249.68 with SMTP id h4mr10397498pls.165.1508203097673; Mon, 16 Oct 2017 18:18:17 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:17 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 09/12] of: overlay: avoid race condition between applying multiple overlays Date: Mon, 16 Oct 2017 18:17:51 -0700 Message-Id: <1508203074-26917-10-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand The process of applying an overlay consists of: - unflatten an overlay FDT (flattened device tree) into an EDT (expanded device tree) - fixup the phandle values in the overlay EDT to fit in a range above the phandle values in the live device tree - create the overlay changeset to reflect the contents of the overlay EDT - apply the overlay changeset, to modify the live device tree, potentially changing the maximum phandle value in the live device tree There is currently no protection against two overlay applies concurrently determining what range of phandle values are in use in the live device tree, and subsequently changing that range. Add a mutex to prevent multiple overlay applies from occurring simultaneously. Move of_resolve_phandles() into of_overlay_apply() so that it does not have to be duplicated by each caller of of_overlay_apply(). The test in of_resolve_phandles() that the overlay tree is detached is temporarily disabled so that old style overlay unittests do not fail. Signed-off-by: Frank Rowand --- drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 6 ------ drivers/of/of_private.h | 12 +++++++++++ drivers/of/overlay.c | 32 ++++++++++++++++++++++++++++ drivers/of/resolver.c | 7 ++++++ drivers/of/unittest.c | 22 +++++++++++++------ include/linux/of.h | 3 --- 6 files changed, 67 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 7a7be0515bfd..54025af534d4 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -145,7 +145,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) __dtb_tilcdc_slave_compat_begin; static void *overlay_data; struct device_node *overlay; - int ret; if (!size) { pr_warn("%s: No overlay data\n", __func__); @@ -164,11 +163,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) } of_node_set_flag(overlay, OF_DETACHED); - ret = of_resolve_phandles(overlay); - if (ret) { - pr_err("%s: Failed to resolve phandles: %d\n", __func__, ret); - return NULL; - } return overlay; } diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index b66e8a812147..03772bdbd94b 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -59,6 +59,18 @@ static inline int of_property_notify(int action, struct device_node *np, } #endif /* CONFIG_OF_DYNAMIC */ +#if defined(CONFIG_OF_RESOLVE) +int of_resolve_phandles(struct device_node *tree); +#endif + +#if defined(CONFIG_OF_OVERLAY) +void of_overlay_mutex_lock(void); +void of_overlay_mutex_unlock(void); +#else +static inline void of_overlay_mutex_lock(void) {}; +static inline void of_overlay_mutex_unlock(void) {}; +#endif + #if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY) extern void __init unittest_unflatten_overlay_base(void); #else diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index a0d3222febdc..b1082c6f7b2c 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -71,6 +71,28 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, const struct device_node *overlay_node, bool is_symbols_node); +/* + * of_resolve_phandles() finds the largest phandle in the live tree. + * of_overlay_apply() may add a larger phandle to the live tree. + * Do not allow race between two overlays being applied simultaneously: + * mutex_lock(&of_overlay_phandle_mutex) + * of_resolve_phandles() + * of_overlay_apply() + * mutex_unlock(&of_overlay_phandle_mutex) + */ +static DEFINE_MUTEX(of_overlay_phandle_mutex); + +void of_overlay_mutex_lock(void) +{ + mutex_lock(&of_overlay_phandle_mutex); +} + +void of_overlay_mutex_unlock(void) +{ + mutex_unlock(&of_overlay_phandle_mutex); +} + + static LIST_HEAD(ovcs_list); static DEFINE_IDR(ovcs_idr); @@ -615,6 +637,12 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id) goto out; } + of_overlay_mutex_lock(); + + ret = of_resolve_phandles(tree); + if (ret) + goto err_overlay_unlock; + mutex_lock(&of_mutex); ret = init_overlay_changeset(ovcs, tree); @@ -660,9 +688,13 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id) } mutex_unlock(&of_mutex); + of_overlay_mutex_unlock(); goto out; +err_overlay_unlock: + of_overlay_mutex_unlock(); + err_free_overlay_changeset: free_overlay_changeset(ovcs); diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 99309cb7d372..8a0f52cfe160 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -275,11 +275,18 @@ int of_resolve_phandles(struct device_node *overlay) err = -EINVAL; goto out; } + +#if 0 + Temporarily disable check so that old style overlay unittests + do not fail when of_resolve_phandles() is moved into + of_overlay_apply(). + if (!of_node_check_flag(overlay, OF_DETACHED)) { pr_err("overlay not detached\n"); err = -EINVAL; goto out; } +#endif phandle_delta = live_tree_max_phandle() + 1; adjust_overlay_phandles(overlay, phandle_delta); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index db2f170186de..cb9b7674f746 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -994,9 +994,17 @@ static int __init unittest_data_add(void) return -ENODATA; } of_node_set_flag(unittest_data_node, OF_DETACHED); + + /* + * This lock normally encloses of_overlay_apply() as well as + * of_resolve_phandles(). + */ + of_overlay_mutex_lock(); + rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); + of_overlay_mutex_unlock(); return -EINVAL; } @@ -1006,6 +1014,7 @@ static int __init unittest_data_add(void) __of_attach_node_sysfs(np); of_aliases = of_find_node_by_path("/aliases"); of_chosen = of_find_node_by_path("/chosen"); + of_overlay_mutex_unlock(); return 0; } @@ -1018,6 +1027,9 @@ static int __init unittest_data_add(void) attach_node_and_children(np); np = next; } + + of_overlay_mutex_unlock(); + return 0; } @@ -2150,16 +2162,11 @@ static int __init overlay_data_add(int onum) } of_node_set_flag(info->np_overlay, OF_DETACHED); - ret = of_resolve_phandles(info->np_overlay); - if (ret) { - pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); - goto out_free_np_overlay; - } - info->overlay_id = 0; ret = of_overlay_apply(info->np_overlay, &info->overlay_id); if (ret < 0) { pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); + of_overlay_mutex_unlock(); goto out_free_np_overlay; } @@ -2209,7 +2216,10 @@ static __init void of_unittest_overlay_high_level(void) * Could not fixup phandles in unittest_unflatten_overlay_base() * because kmalloc() was not yet available. */ + of_overlay_mutex_lock(); of_resolve_phandles(overlay_base_root); + of_overlay_mutex_unlock(); + /* * do not allow overlay_base to duplicate any node already in diff --git a/include/linux/of.h b/include/linux/of.h index 49e5f24fb390..55e9ff0fb1fe 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1273,9 +1273,6 @@ static inline int of_reconfig_get_state_change(unsigned long action, } #endif /* CONFIG_OF_DYNAMIC */ -/* CONFIG_OF_RESOLVE api */ -extern int of_resolve_phandles(struct device_node *tree); - /** * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node * @np: Pointer to the given device_node From patchwork Tue Oct 17 01:17:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826690 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FDYkg/bw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHR50V7nz9sPk for ; Tue, 17 Oct 2017 12:19:29 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758133AbdJQBSz (ORCPT ); Mon, 16 Oct 2017 21:18:55 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:49101 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757690AbdJQBST (ORCPT ); Mon, 16 Oct 2017 21:18:19 -0400 Received: by mail-pg0-f67.google.com with SMTP id v78so126500pgb.5; Mon, 16 Oct 2017 18:18:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8JYnK2oRje84AP+LZCs26LhmA6CmqhqteQO7oXuHhBs=; b=FDYkg/bwe4SliXSdLND4/oOoWzcLtpEiQarDipYiUPe6ci3eTRXkQ+FUTfs9/MXzdi KVWLlf61PPqg0PNrglJhlKPj2/9gtRs97M6JznhtwZYSsdgEnV/epZDBetIK+kJDaaqn dvGUFTTEF7nEJVDPEuFNuk92c/hpfjHuCQ5ivLyTFwRnaNsN6uZeRCi7gti8aZ1xzUzZ Gd5vodbH77kMn3mqUFr2d41qWM2BlSGGFq+DE+0252MdGX3n8ho1K5LFWHJ4MiPd1Gu1 GJCSZ3C2u0wEdOxUUb1CMjvBp+nGh2+u701EMsbBR23Xv5XdnQOsvIwIORZ5s+uUUuHh Xeug== 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:in-reply-to :references; bh=8JYnK2oRje84AP+LZCs26LhmA6CmqhqteQO7oXuHhBs=; b=DPi/hjwajfdamnCabIm3KE+hYUHBO8QM+4QR2Mt0Vfb3L62AGGYOyRSHl+wtnVhhXS p5f2A5kHpFN7TVLiuc507v6fG9GWkeOXXWF9rXM4cFcdlOe7BlZe/dnD5hNb5qQUZl67 1U7PqiABYONb/UaHo24YFycVKbO5edrknzKNuRF87Iya6/TnMaYlK5bhhysEXNH6UsvF MBc3Q0QO9XF1sYRVjQqPVRct9x7lseZYVcs9ncG+TBDpyh9dZoEloNgb0qhxVbrJm9CW 37PUCjdXl9snEHJVrXxHsOLoDf9jcfFB/XJARjqUYMC6ywtZPJwz1TUEIul1Yh0WkS7M k9Ig== X-Gm-Message-State: AMCzsaXqItbbK406DDrWoSWvfGn83zWVJG4NBnlozaxaj8UrdDVmPIMC 3ZcTUq7Yig0kHkPSycNprcM= X-Google-Smtp-Source: AOwi7QDzpIQCiTBJ4A0vTfm49TjXR6nz86G6fZgvMKRRfQI+CIZ8Hu4joVPCa83tirCPFNsKuCN5Tg== X-Received: by 10.98.103.72 with SMTP id b69mr10165466pfc.251.1508203098917; Mon, 16 Oct 2017 18:18:18 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:18 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 10/12] of: overlay: simplify applying symbols from an overlay Date: Mon, 16 Oct 2017 18:17:52 -0700 Message-Id: <1508203074-26917-11-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand The code to apply symbols from an overlay to the live device tree was implemented with the intent to be minimally intrusive on the existing code. After recent restructuring of the overlay apply code, it is easier to disintangle the code that applies the symbols, and to make the overlay changeset creation code more straight forward and understandable. Remove the extra complexity, and make the code more obvious. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 91 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index b1082c6f7b2c..912c222ff011 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -32,21 +32,22 @@ struct fragment { struct device_node *target; struct device_node *overlay; - bool is_symbols_node; }; /** * struct overlay_changeset - * @ovcs_list: list on which we are located - * @count: count of @fragments structures - * @fragments: info about fragment nodes in overlay expanded device tree - * @cset: changeset to apply fragments to live device tree + * @ovcs_list: list on which we are located + * @count: count of fragment structures + * @fragments: fragment nodes in the overlay expanded device tree + * @symbols_fragment: last element of @fragments[] is the __symbols__ node + * @cset: changeset to apply fragments to live device tree */ struct overlay_changeset { int id; struct list_head ovcs_list; int count; struct fragment *fragments; + bool symbols_fragment; struct of_changeset cset; }; @@ -68,8 +69,7 @@ static int devicetree_corrupt(void) static int build_changeset_next_level(struct overlay_changeset *ovcs, struct device_node *target_node, - const struct device_node *overlay_node, - bool is_symbols_node); + const struct device_node *overlay_node); /* * of_resolve_phandles() finds the largest phandle in the live tree. @@ -221,7 +221,7 @@ static struct property *dup_and_fixup_symbol_prop( * @ovcs: overlay changeset * @target_node: where to place @overlay_prop in live tree * @overlay_prop: property to add or update, from overlay tree - * is_symbols_node: 1 if @target_node is "/__symbols__" + * @is_symbols_prop: 1 if @overlay_prop is from node "/__symbols__" * * If @overlay_prop does not already exist in @target_node, add changeset entry * to add @overlay_prop in @target_node, else add changeset entry to update @@ -237,7 +237,7 @@ static struct property *dup_and_fixup_symbol_prop( static int add_changeset_property(struct overlay_changeset *ovcs, struct device_node *target_node, struct property *overlay_prop, - bool is_symbols_node) + bool is_symbols_prop) { struct property *new_prop = NULL, *prop; @@ -248,7 +248,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs, !of_prop_cmp(overlay_prop->name, "linux,phandle")) return 0; - if (is_symbols_node) { + if (is_symbols_prop) { if (prop) return -EINVAL; new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop); @@ -321,13 +321,13 @@ static int add_changeset_node(struct overlay_changeset *ovcs, if (ret) return ret; - return build_changeset_next_level(ovcs, tchild, node, 0); + return build_changeset_next_level(ovcs, tchild, node); } if (node->phandle && tchild->phandle) ret = -EINVAL; else - ret = build_changeset_next_level(ovcs, tchild, node, 0); + ret = build_changeset_next_level(ovcs, tchild, node); of_node_put(tchild); return ret; @@ -338,7 +338,6 @@ static int add_changeset_node(struct overlay_changeset *ovcs, * @ovcs: overlay changeset * @target_node: where to place @overlay_node in live tree * @overlay_node: node from within an overlay device tree fragment - * @is_symbols_node: @overlay_node is node "/__symbols__" * * Add the properties (if any) and nodes (if any) from @overlay_node to the * @ovcs->cset changeset. If an added node has child nodes, they will @@ -351,16 +350,14 @@ static int add_changeset_node(struct overlay_changeset *ovcs, */ static int build_changeset_next_level(struct overlay_changeset *ovcs, struct device_node *target_node, - const struct device_node *overlay_node, - bool is_symbols_node) + const struct device_node *overlay_node) { struct device_node *child; struct property *prop; int ret; for_each_property_of_node(overlay_node, prop) { - ret = add_changeset_property(ovcs, target_node, prop, - is_symbols_node); + ret = add_changeset_property(ovcs, target_node, prop, 0); if (ret) { pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", target_node, prop->name, ret); @@ -368,9 +365,6 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, } } - if (is_symbols_node) - return 0; - for_each_child_of_node(overlay_node, child) { ret = add_changeset_node(ovcs, target_node, child); if (ret) { @@ -384,6 +378,28 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, return 0; } +/* + * Add the properties from __overlay__ node to the @ovcs->cset changeset. + */ +static int build_changeset_symbols_node(struct overlay_changeset *ovcs, + struct device_node *target_node, + const struct device_node *overlay_symbols_node) +{ + struct property *prop; + int ret; + + for_each_property_of_node(overlay_symbols_node, prop) { + ret = add_changeset_property(ovcs, target_node, prop, 1); + if (ret) { + pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", + target_node, prop->name, ret); + return ret; + } + } + + return 0; +} + /** * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments * @ovcs: Overlay changeset @@ -398,14 +414,33 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, */ static int build_changeset(struct overlay_changeset *ovcs) { - int i, ret; + struct fragment *fragment; + int fragments_count, i, ret; - for (i = 0; i < ovcs->count; i++) { - struct fragment *fragment = &ovcs->fragments[i]; + /* + * if there is a symbols fragment in ovcs->fragments[i] it is + * the final element in the array + */ + if (ovcs->symbols_fragment) + fragments_count = ovcs->count - 1; + else + fragments_count = ovcs->count; + + for (i = 0; i < fragments_count; i++) { + fragment = &ovcs->fragments[i]; ret = build_changeset_next_level(ovcs, fragment->target, - fragment->overlay, - fragment->is_symbols_node); + fragment->overlay); + if (ret) { + pr_debug("apply failed '%pOF'\n", fragment->target); + return ret; + } + } + + if (ovcs->symbols_fragment) { + fragment = &ovcs->fragments[ovcs->count - 1]; + ret = build_changeset_symbols_node(ovcs, fragment->target, + fragment->overlay); if (ret) { pr_debug("apply failed '%pOF'\n", fragment->target); return ret; @@ -522,12 +557,16 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, } } + /* + * if there is a symbols fragment in ovcs->fragments[i] it is + * the final element in the array + */ node = of_get_child_by_name(tree, "__symbols__"); if (node) { + ovcs->symbols_fragment = 1; fragment = &fragments[cnt]; fragment->overlay = node; fragment->target = of_find_node_by_path("/__symbols__"); - fragment->is_symbols_node = 1; if (!fragment->target) { pr_err("no symbols in root of device tree.\n"); From patchwork Tue Oct 17 01:17:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826688 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cDu/7DfM"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHQD3Pphz9t2c for ; Tue, 17 Oct 2017 12:18:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757776AbdJQBSX (ORCPT ); Mon, 16 Oct 2017 21:18:23 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:46913 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757701AbdJQBSU (ORCPT ); Mon, 16 Oct 2017 21:18:20 -0400 Received: by mail-pf0-f193.google.com with SMTP id p87so127057pfj.3; Mon, 16 Oct 2017 18:18:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zFR/3rgA6r142YtYxqy0fvIW0XaYs+kiJX9Ovq51zew=; b=cDu/7DfMLu+g0fBr8T/Zrj2nVk9ys71bomJdRXj+eOsA5KAjkctAkN6P+DL2a7yWD+ Ka9Tu8PWEByMobDm7ZgbB7tadW+7cpzrLycGtOjV/13yrwjNsxNsTVW5ryxTj00U1PtQ NYtLcdMqmPut3LE8n6svbSSvlKAqUOZiKLF19iTAoxnjz55tayiPXtPDN7k031nNenAI 5+W7Eql9w/g/dhYYM+JBhGb01Pwt62pEKDIyNVRjux9hXSYY6vaEgRXtyK1UMv8kI4Dl RhrkDlP4ky/BeLb7s1pLcfVeAMwQ3hBDDVtfGKk0zbignd8ID0I07WNTpE5q2b2b4IuN XDVA== 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:in-reply-to :references; bh=zFR/3rgA6r142YtYxqy0fvIW0XaYs+kiJX9Ovq51zew=; b=f2/oDOcQ8KUWV2HmTbE8D5CpRjoSCfZcHkUqW97MMfCUwnYX8vggXAEjlQ8StDUn7C +TnOZyoJEYwtIFhsdymYv/jyDe5ZU53gV+U+LN3zCf1UN+arvYt6qseC3W5vKVWaYbCs FIpIJKOOIzlBV/8p/eeDFjhCaxe0dc6N8s5H8rvHFT67Onyl0EYMUlOJQQ6WMNTq3NP5 EirxIxuT0/TdeVFmp4NbT3O9Cq7TnfNKMBDqwlyfmvFGPQPVF3Mt0qPah9Eu2YkE3Psn EaFCO+PpHpV8fmRPYjMr0vCmGBere1Hb6wHZHF2ju78NbZDBAkfMsZGfazcPk61baRa2 U9Rg== X-Gm-Message-State: AMCzsaVTlZn5aepQGP2u/3L08FIa/zDS2Uo9eUbkYm4tiXiCn97a2AI5 mIeMScvHPGT1QmOdlLM88D0= X-Google-Smtp-Source: ABhQp+SnDBNk7RunczSM+NiHL2KcX+rlyIn1RcAUfuV5hQ6IndD2upzapZUzGJmizoaB2599XI9X0A== X-Received: by 10.84.129.36 with SMTP id 33mr2329957plb.303.1508203100138; Mon, 16 Oct 2017 18:18:20 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:19 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 11/12] of: overlay: remove a dependency on device node full_name Date: Mon, 16 Oct 2017 18:17:53 -0700 Message-Id: <1508203074-26917-12-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand The "%pOF" printf format was recently added to print the full name of a device tree node, with the intent of changing the node full_name field to contain only the node name instead of the full path of the node. dup_and_fixup_symbol_prop() duplicates a property from the "/__symbols__" node of an overlay device tree. The value of each duplicated property must be fixed up to include the full path of a node in the live device tree. The current code uses the node's full_name for that purpose. Update the code to use the "%pOF" printf format to determine the node's full path. Signed-off-by: Frank Rowand --- drivers/of/base.c | 2 +- drivers/of/of_private.h | 2 ++ drivers/of/overlay.c | 90 ++++++++++++++++++++++++++++++------------------- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 260d33c0f26c..6f91fa67e5bb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -760,7 +760,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node, } EXPORT_SYMBOL(of_get_child_by_name); -static struct device_node *__of_find_node_by_path(struct device_node *parent, +struct device_node *__of_find_node_by_path(struct device_node *parent, const char *path) { struct device_node *child; diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 03772bdbd94b..267edb1b50df 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -93,6 +93,8 @@ extern void *__unflatten_device_tree(const void *blob, struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); __printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...); +struct device_node *__of_find_node_by_path(struct device_node *parent, + const char *path); struct device_node *__of_find_node_by_full_path(struct device_node *node, const char *path); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 912c222ff011..a257474c9223 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -37,6 +37,7 @@ struct fragment { /** * struct overlay_changeset * @ovcs_list: list on which we are located + * @overlay_tree: expanded device tree that contains the fragment nodes * @count: count of fragment structures * @fragments: fragment nodes in the overlay expanded device tree * @symbols_fragment: last element of @fragments[] is the __symbols__ node @@ -45,6 +46,7 @@ struct fragment { struct overlay_changeset { int id; struct list_head ovcs_list; + struct device_node *overlay_tree; int count; struct fragment *fragments; bool symbols_fragment; @@ -145,12 +147,13 @@ static int overlay_notify(struct overlay_changeset *ovcs, } /* - * The properties in the "/__symbols__" node are "symbols". + * The values of properties in the "/__symbols__" node are paths in + * the ovcs->overlay_tree. When duplicating the properties, the paths + * need to be adjusted to be the correct path for the live device tree. * - * The value of properties in the "/__symbols__" node is the path of a - * node in the subtree of a fragment node's "__overlay__" node, for - * example "/fragment@0/__overlay__/symbol_path_tail". Symbol_path_tail - * can be a single node or it may be a multi-node path. + * The paths refer to a node in the subtree of a fragment node's "__overlay__" + * node, for example "/fragment@0/__overlay__/symbol_path_tail", + * where symbol_path_tail can be a single node or it may be a multi-node path. * * The duplicated property value will be modified by replacing the * "/fragment_name/__overlay/" portion of the value with the target @@ -160,59 +163,76 @@ static struct property *dup_and_fixup_symbol_prop( struct overlay_changeset *ovcs, const struct property *prop) { struct fragment *fragment; - struct property *new; - const char *overlay_name; - char *symbol_path_tail; - char *symbol_path; + struct property *new_prop; + struct device_node *fragment_node; + struct device_node *overlay_node; + const char *path; + const char *path_tail; const char *target_path; int k; - int symbol_path_tail_len; int overlay_name_len; + int path_len; + int path_tail_len; int target_path_len; if (!prop->value) return NULL; - symbol_path = prop->value; + if (strnlen(prop->value, prop->length) >= prop->length) + return NULL; + path = prop->value; + path_len = strlen(path); - new = kzalloc(sizeof(*new), GFP_KERNEL); - if (!new) + if (path_len < 1) return NULL; + fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1); + overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/"); + of_node_put(fragment_node); + of_node_put(overlay_node); for (k = 0; k < ovcs->count; k++) { fragment = &ovcs->fragments[k]; - overlay_name = fragment->overlay->full_name; - overlay_name_len = strlen(overlay_name); - if (!strncasecmp(symbol_path, overlay_name, overlay_name_len)) + if (fragment->overlay == overlay_node) break; } - if (k >= ovcs->count) - goto err_free; + return NULL; + + overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay); - target_path = fragment->target->full_name; + if (overlay_name_len > path_len) + return NULL; + path_tail = path + overlay_name_len; + path_tail_len = strlen(path_tail); + + target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target); + if (!target_path) + return NULL; target_path_len = strlen(target_path); - symbol_path_tail = symbol_path + overlay_name_len; - symbol_path_tail_len = strlen(symbol_path_tail); + new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); + if (!new_prop) + goto err_free_target_path; - new->name = kstrdup(prop->name, GFP_KERNEL); - new->length = target_path_len + symbol_path_tail_len + 1; - new->value = kzalloc(new->length, GFP_KERNEL); + new_prop->name = kstrdup(prop->name, GFP_KERNEL); + new_prop->length = target_path_len + path_tail_len + 1; + new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); + if (!new_prop->name || !new_prop->value) + goto err_free_new_prop; - if (!new->name || !new->value) - goto err_free; + strcpy(new_prop->value, target_path); + strcpy(new_prop->value + target_path_len, path_tail); - strcpy(new->value, target_path); - strcpy(new->value + target_path_len, symbol_path_tail); + of_property_set_flag(new_prop, OF_DYNAMIC); - of_property_set_flag(new, OF_DYNAMIC); + return new_prop; - return new; +err_free_new_prop: + kfree(new_prop->name); + kfree(new_prop->value); + kfree(new_prop); +err_free_target_path: + kfree(target_path); - err_free: - kfree(new->name); - kfree(new->value); - kfree(new); return NULL; } @@ -510,6 +530,8 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, if (!of_node_is_root(tree)) pr_debug("%s() tree is not root\n", __func__); + ovcs->overlay_tree = tree; + INIT_LIST_HEAD(&ovcs->ovcs_list); of_changeset_init(&ovcs->cset); From patchwork Tue Oct 17 01:17:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 826687 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="LxzrhYed"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yGHQ7404pz9sPk for ; Tue, 17 Oct 2017 12:18:39 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757701AbdJQBSY (ORCPT ); Mon, 16 Oct 2017 21:18:24 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:45664 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754063AbdJQBSV (ORCPT ); Mon, 16 Oct 2017 21:18:21 -0400 Received: by mail-pg0-f68.google.com with SMTP id b192so130843pga.2; Mon, 16 Oct 2017 18:18:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8ZFGDqGMIBtqYydcPFJE5TbA+os+2K/Fktdvpqk16eQ=; b=LxzrhYed2PLgT5qgndgN6TvHyrwxMgVsdZvsFJ/IK6K9YLl2hjGY8IdP7GoStDnssG C+T08XeneeduLpt9uefWoeRLfjypuKMx4S3RwHIu3TF32fd6TrbfCXpeZ8WEUFN2UIU7 XTlPibp8rzcoz6+M+BX1gTbDynRM31/NVmEKKwxYSgSbJmKPLc7XxzP+s/8fXnqPzCuz 6QtpkAtKsGmN+WhY9SyauxaoPkcmurrScO5zv0v8L+NgKVwVSsY/Mhe2/oYTqU3uYVnA Qo99XI87PMJHjtcVlxujJw/Y7qs2m82m0z2UDxsUZol9cc4yTjiUcPIGrtxXmhycp+bB F76g== 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:in-reply-to :references; bh=8ZFGDqGMIBtqYydcPFJE5TbA+os+2K/Fktdvpqk16eQ=; b=txXEJteBDpH3n6lxUqj08gocES3UDAExXyqxw4QqCjZcQrk99ZDWMuJGgXyeec8iir 5gpR0b4J/pmJcB3Z04Fbu2jnALZhXrx6e+gOan0gRhrm7BEVx0D6Zwt8J94ZwPIjBmTl oTUdj5CHOhKMTdO1NIlDfDJ+BwKoGYuqKSsulSSWR+ZASZjNnQsreczBdtB0Xqa8HjO7 tWryHM1fTGk6o/lrzaBMCI7quuyl8AmyGD0Pg/Cu9dOjp9H469flOWD2m10/QcMUqoZE Z5fkalRN0ahEiVwZwX2ysCAXxCDLTO08vb/nj8tMogWBQ8OtvOrPG4r96MfE28trhLkQ bS8w== X-Gm-Message-State: AMCzsaUOkAhhcdwljk7OE3TXOsninNQEKVPAJ0TeyFCaJZ4NpmtNKbOL RStnyIMeYt3mwgrSbKSmQQ0= X-Google-Smtp-Source: AOwi7QB4xqualXFXtAGumSSHZrHJ/2YTweKwRBtnCX2GBt8DA6pmviL6sTpVh2Xxd3YO331XXIpzIg== X-Received: by 10.99.147.69 with SMTP id w5mr9485225pgm.401.1508203101326; Mon, 16 Oct 2017 18:18:21 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id f1sm16874283pfe.150.2017.10.16.18.18.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Oct 2017 18:18:20 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Rutland , Tomi Valkeinen , dri-devel@lists.freedesktop.org Subject: [PATCH v2 12/12] of: overlay: remove unneeded check for NULL kbasename() Date: Mon, 16 Oct 2017 18:17:54 -0700 Message-Id: <1508203074-26917-13-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> References: <1508203074-26917-1-git-send-email-frowand.list@gmail.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Frank Rowand kbasename() will not return NULL if passed a valid string. If the parameter passed to kbasename() in this case is already NULL then the devicetree has been corrupted. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index a257474c9223..dc7657329aea 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -322,8 +322,6 @@ static int add_changeset_node(struct overlay_changeset *ovcs, int ret = 0; node_kbasename = kbasename(node->full_name); - if (!node_kbasename) - return -ENOMEM; for_each_child_of_node(target_node, tchild) if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))