summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@sony.com>2017-10-17 16:36:27 -0700
committerRob Herring <robh@kernel.org>2017-10-17 20:47:17 -0500
commit87f242c119c403e8b948c8b95eca4ab6212fd1a9 (patch)
treec1021c251252faf1fc9dbea35baca06d5d36780b
parent24789c5ce5a373dd55640f9cd79117fcc3ccc46d (diff)
downloadlinux-87f242c119c403e8b948c8b95eca4ab6212fd1a9.tar.bz2
of: overlay: expand check of whether overlay changeset can be removed
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 <frank.rowand@sony.com> Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r--drivers/of/overlay.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 78c50fd57750..4cdee169a5ab 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -707,13 +707,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;
@@ -723,10 +723,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;
}
}
@@ -750,7 +756,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;
}