2017-07-19 16:25:47

by Frank Rowand

[permalink] [raw]
Subject: [PATCH v4 0/3] of: overlay: load overlay symbols into live device tree

From: Frank Rowand <[email protected]>

Symbols in a loaded overlay are not currently available to subsequently
loaded overlays because the properties in the overlay's __symbols__
node are not loaded into the live device tree.

Patch 1 is unittests to test patches 2 and 3.

Patch 2 fixes a problem discovered while developing patch 3. If
a node name in an overlay has a unit-address then the overlay
code does not correctly match the node name against an existing
node in the live tree.

Patch 3 adds the properties in an overlay's __symbol__ node to
the overlay changeset.

changes since v3:
- fix make W=2 warnings in overlay_base.dts and overlay.dts
- update the test results in the patch comments to match the
.dts changes

changes since v2:
- test on 4.13-rc1
- remove redundant comments from patch headers of patch 0 and patch 1
- guard make of overlay .dtb files with CONFIG_OF_OVERLAY
- guard unittest.c references to overlay .dtb files with
CONFIG_OF_OVERLAY

changes since v1:
- patch 2: Use for_each_child_of_node() instead of open coding,
which allowed removing the new function child_by_full_name().



Frank Rowand (3):
of: overlay: add overlay unittest data for node names and symbols
of: overlay: correctly apply overlay node with unit-address
of: overlay: add overlay symbols to live device tree

drivers/of/overlay.c | 121 ++++++++++++++++++++++--
drivers/of/unittest-data/Makefile | 19 +++-
drivers/of/unittest-data/overlay.dts | 25 ++++-
drivers/of/unittest-data/overlay_bad_symbol.dts | 22 +++++
drivers/of/unittest-data/overlay_base.dts | 11 +++
drivers/of/unittest.c | 10 +-
6 files changed, 190 insertions(+), 18 deletions(-)
create mode 100644 drivers/of/unittest-data/overlay_bad_symbol.dts

--
Frank Rowand <[email protected]>


2017-07-19 16:25:49

by Frank Rowand

[permalink] [raw]
Subject: [PATCH v4 1/3] of: overlay: add overlay unittest data for node names and symbols

From: Frank Rowand <[email protected]>

Add nodes and properties to overlay_base and overlay dts files to
test for
- incorrect existing node name detection when overlay node name
has a unit-address
- adding overlay __symbols__ properties to live tree when an
overlay is added to the live tree

The following console messages will appear near the end of unittest
until the code errors are corrected:

OF: Duplicate name in fairway-1, renamed to "ride@100#1"

### dt-test ### FAIL of_unittest_overlay_high_level():2296 Adding overlay 'overlay_bad_symbol' failed

### dt-test ### end of unittest - 190 passed, 1 failed

Signed-off-by: Frank Rowand <[email protected]>
---
drivers/of/unittest-data/Makefile | 19 ++++++++++++++-----
drivers/of/unittest-data/overlay.dts | 25 ++++++++++++++++++++++++-
drivers/of/unittest-data/overlay_bad_symbol.dts | 22 ++++++++++++++++++++++
drivers/of/unittest-data/overlay_base.dts | 11 +++++++++++
drivers/of/unittest.c | 10 ++++++++--
5 files changed, 79 insertions(+), 8 deletions(-)
create mode 100644 drivers/of/unittest-data/overlay_bad_symbol.dts

diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile
index 6e00a9c69e58..2d135fba94c1 100644
--- a/drivers/of/unittest-data/Makefile
+++ b/drivers/of/unittest-data/Makefile
@@ -1,18 +1,27 @@
obj-y += testcases.dtb.o
+
+targets += testcases.dtb testcases.dtb.S
+
+ifdef CONFIG_OF_OVERLAY
+
obj-y += overlay.dtb.o
obj-y += overlay_bad_phandle.dtb.o
+obj-y += overlay_bad_symbol.dtb.o
obj-y += overlay_base.dtb.o

-targets += testcases.dtb testcases.dtb.S
targets += overlay.dtb overlay.dtb.S
targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S
+targets += overlay_bad_symbol.dtb overlay_bad_symbol.dtb.S
targets += overlay_base.dtb overlay_base.dtb.S

-.PRECIOUS: \
- $(obj)/%.dtb.S \
- $(obj)/%.dtb
-
# enable creation of __symbols__ node
DTC_FLAGS_overlay := -@
DTC_FLAGS_overlay_bad_phandle := -@
+DTC_FLAGS_overlay_bad_symbol := -@
DTC_FLAGS_overlay_base := -@
+
+endif
+
+.PRECIOUS: \
+ $(obj)/%.dtb.S \
+ $(obj)/%.dtb
diff --git a/drivers/of/unittest-data/overlay.dts b/drivers/of/unittest-data/overlay.dts
index 6cd7e6a0c13e..60abf5b55cae 100644
--- a/drivers/of/unittest-data/overlay.dts
+++ b/drivers/of/unittest-data/overlay.dts
@@ -25,7 +25,22 @@
#size-cells = <1>;
status = "ok";

- ride@200 {
+ ride@100 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ track@30 {
+ incline-up = < 48 32 16 >;
+ };
+
+ track@40 {
+ incline-up = < 47 31 15 >;
+ };
+ };
+
+ ride_200: ride@200 {
+ #address-cells = <1>;
+ #size-cells = <1>;
compatible = "ot,ferris-wheel";
reg = < 0x00000200 0x100 >;
hvac-provider = < &hvac_2 >;
@@ -36,6 +51,14 @@
spin-rph = < 30 >;
gondolas = < 16 >;
gondola-capacity = < 6 >;
+
+ ride_200_left: track@10 {
+ reg = < 0x00000010 0x10 >;
+ };
+
+ ride_200_right: track@20 {
+ reg = < 0x00000020 0x10 >;
+ };
};
};
};
diff --git a/drivers/of/unittest-data/overlay_bad_symbol.dts b/drivers/of/unittest-data/overlay_bad_symbol.dts
new file mode 100644
index 000000000000..09261cb9a67e
--- /dev/null
+++ b/drivers/of/unittest-data/overlay_bad_symbol.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+
+ fragment@0 {
+ target = <&electric_1>;
+
+ __overlay__ {
+
+ // This label should cause an error when the overlay
+ // is applied. There is already a symbol hvac_1
+ // in the base tree
+ hvac_1: hvac-medium-2 {
+ compatible = "ot,hvac-medium";
+ heat-range = < 50 75 >;
+ cool-range = < 60 80 >;
+ };
+
+ };
+ };
+};
diff --git a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts
index 5566b27fb61a..453d0bd83320 100644
--- a/drivers/of/unittest-data/overlay_base.dts
+++ b/drivers/of/unittest-data/overlay_base.dts
@@ -44,6 +44,8 @@
orientation = < 127 >;

ride@100 {
+ #address-cells = <1>;
+ #size-cells = <1>;
compatible = "ot,roller-coaster";
reg = < 0x00000100 0x100 >;
hvac-provider = < &hvac_1 >;
@@ -53,6 +55,15 @@
spin-controller = < &spin_ctrl_2 5 &spin_ctrl_2 7 >;
spin-controller-names = "track_1", "track_2";
queues = < 2 >;
+
+ track@30 {
+ reg = < 0x00000030 0x10 >;
+ };
+
+ track@40 {
+ reg = < 0x00000040 0x10 >;
+ };
+
};
};

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 0107fc680335..12d08419b736 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1983,6 +1983,8 @@ static void __init of_unittest_overlay(void)
static inline void __init of_unittest_overlay(void) { }
#endif

+#ifdef CONFIG_OF_OVERLAY
+
/*
* __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
* in scripts/Makefile.lib
@@ -2010,14 +2012,14 @@ struct overlay_info {
OVERLAY_INFO_EXTERN(overlay_base);
OVERLAY_INFO_EXTERN(overlay);
OVERLAY_INFO_EXTERN(overlay_bad_phandle);
-
-#ifdef CONFIG_OF_OVERLAY
+OVERLAY_INFO_EXTERN(overlay_bad_symbol);

/* order of entries is hard-coded into users of overlays[] */
static struct overlay_info overlays[] = {
OVERLAY_INFO(overlay_base, -9999),
OVERLAY_INFO(overlay, 0),
OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
+ OVERLAY_INFO(overlay_bad_symbol, -EINVAL),
{}
};

@@ -2289,6 +2291,10 @@ static __init void of_unittest_overlay_high_level(void)

unittest(overlay_data_add(2),
"Adding overlay 'overlay_bad_phandle' failed\n");
+
+ unittest(overlay_data_add(3),
+ "Adding overlay 'overlay_bad_symbol' failed\n");
+
return;

err_unlock:
--
Frank Rowand <[email protected]>

2017-07-19 16:25:57

by Frank Rowand

[permalink] [raw]
Subject: [PATCH v4 3/3] of: overlay: add overlay symbols to live device tree

From: Frank Rowand <[email protected]>

Add overlay __symbols__ properties to live tree when an overlay
is added to the live tree so that the symbols are available to
subsequent overlays.

Expected test result is new __symbols__ entries for labels from
the overlay after this commit.

Before this commit:

Console error message near end of unittest:
### dt-test ### FAIL of_unittest_overlay_high_level():2296 Adding overlay 'overlay_bad_symbol' failed
### dt-test ### end of unittest - 190 passed, 1 failed

The new unittest "fails" because the expected result of loading the
new overlay is an error instead of success.

$ # node hvac-medium-2 exists because the overlay loaded
$ # since the duplicate symbol was not detected
$ cd /proc/device-tree/testcase-data-2/substation@100/
$ ls
compatible hvac-medium-2 motor-8 reg
hvac-large-1 linux,phandle name status
hvac-medium-1 motor-1 phandle

$ cd /proc/device-tree/__symbols__/
$ ls
electric_1 lights_1 name rides_1 spin_ctrl_2
hvac_1 lights_2 retail_1 spin_ctrl_1

After this commit:

Previous console error message no longer occurs, but expected error
occurs:
OF: overlay: Failed to apply prop @/__symbols__/hvac_1
OF: overlay: apply failed '/__symbols__'
### dt-test ### end of unittest - 191 passed, 0 failed

$ # node hvac-medium-2 does not exist because the overlay
$ # properly failed to load due to the duplicate symbol
$ cd /proc/device-tree/testcase-data-2/substation@100/
$ ls
compatible hvac-medium-1 motor-1 name reg
hvac-large-1 linux,phandle motor-8 phandle status

$ cd /proc/device-tree/__symbols__/
$ ls
electric_1 lights_1 retail_1 ride_200_right spin_ctrl_2
hvac_1 lights_2 ride_200 rides_1
hvac_2 name ride_200_left spin_ctrl_1
$ cat ride_200; echo
/testcase-data-2/fairway-1/ride@200
$ cat ride_200_left ; echo
/testcase-data-2/fairway-1/ride@200/track@10
$ cat ride_200_right ; echo
/testcase-data-2/fairway-1/ride@200/track@20

Signed-off-by: Frank Rowand <[email protected]>
---
drivers/of/overlay.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 107 insertions(+), 9 deletions(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index bd3c32f2d411..b7fe9817b644 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -35,6 +35,7 @@
struct of_overlay_info {
struct device_node *target;
struct device_node *overlay;
+ bool is_symbols_node;
};

/**
@@ -55,7 +56,8 @@ struct of_overlay {
};

static int of_overlay_apply_one(struct of_overlay *ov,
- struct device_node *target, const struct device_node *overlay);
+ struct device_node *target, const struct device_node *overlay,
+ bool is_symbols_node);

static BLOCKING_NOTIFIER_HEAD(of_overlay_chain);

@@ -92,10 +94,74 @@ 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)
+{
+ struct of_overlay_info *ovinfo;
+ struct property *new;
+ const char *overlay_name;
+ char *label_path;
+ char *symbol_path;
+ const char *target_path;
+ int k;
+ int label_path_len;
+ int overlay_name_len;
+ int target_path_len;
+
+ if (!prop->value)
+ return NULL;
+ symbol_path = prop->value;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ return NULL;
+
+ for (k = 0; k < ov->count; k++) {
+ ovinfo = &ov->ovinfo_tab[k];
+ overlay_name = ovinfo->overlay->full_name;
+ overlay_name_len = strlen(overlay_name);
+ if (!strncasecmp(symbol_path, overlay_name, overlay_name_len))
+ break;
+ }
+
+ if (k >= ov->count)
+ goto err_free;
+
+ target_path = ovinfo->target->full_name;
+ target_path_len = strlen(target_path);
+
+ label_path = symbol_path + overlay_name_len;
+ label_path_len = strlen(label_path);
+
+ new->name = kstrdup(prop->name, GFP_KERNEL);
+ new->length = target_path_len + label_path_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);
+
+ /* mark the property as dynamic */
+ of_property_set_flag(new, OF_DYNAMIC);
+
+ return new;
+
+ err_free:
+ kfree(new->name);
+ kfree(new->value);
+ kfree(new);
+ return NULL;
+
+
+}
+
static int of_overlay_apply_single_property(struct of_overlay *ov,
- struct device_node *target, struct property *prop)
+ struct device_node *target, struct property *prop,
+ bool is_symbols_node)
{
- struct property *propn, *tprop;
+ struct property *propn = NULL, *tprop;

/* NOTE: Multiple changes of single properties not supported */
tprop = of_find_property(target, prop->name, NULL);
@@ -106,7 +172,15 @@ static int of_overlay_apply_single_property(struct of_overlay *ov,
of_prop_cmp(prop->name, "linux,phandle") == 0)
return 0;

- propn = __of_prop_dup(prop, GFP_KERNEL);
+ if (is_symbols_node) {
+ /* changing a property in __symbols__ node not allowed */
+ if (tprop)
+ return -EINVAL;
+ propn = dup_and_fixup_symbol_prop(ov, prop);
+ } else {
+ propn = __of_prop_dup(prop, GFP_KERNEL);
+ }
+
if (propn == NULL)
return -ENOMEM;

@@ -140,7 +214,7 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
return -EINVAL;

/* apply overlay recursively */
- ret = of_overlay_apply_one(ov, tchild, child);
+ ret = of_overlay_apply_one(ov, tchild, child, 0);
of_node_put(tchild);
} else {
/* create empty tree as a target */
@@ -155,7 +229,7 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
if (ret)
return ret;

- ret = of_overlay_apply_one(ov, tchild, child);
+ ret = of_overlay_apply_one(ov, tchild, child, 0);
if (ret)
return ret;
}
@@ -171,14 +245,16 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
* by using the changeset.
*/
static int of_overlay_apply_one(struct of_overlay *ov,
- struct device_node *target, const struct device_node *overlay)
+ struct device_node *target, const struct device_node *overlay,
+ 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);
+ ret = of_overlay_apply_single_property(ov, target, prop,
+ is_symbols_node);
if (ret) {
pr_err("Failed to apply prop @%s/%s\n",
target->full_name, prop->name);
@@ -186,6 +262,10 @@ 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;
+
for_each_child_of_node(overlay, child) {
ret = of_overlay_apply_single_device_node(ov, target, child);
if (ret != 0) {
@@ -216,7 +296,8 @@ static int of_overlay_apply(struct of_overlay *ov)
for (i = 0; i < ov->count; i++) {
struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i];

- err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay);
+ err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay,
+ ovinfo->is_symbols_node);
if (err != 0) {
pr_err("apply failed '%s'\n", ovinfo->target->full_name);
return err;
@@ -314,6 +395,9 @@ static int of_build_overlay_info(struct of_overlay *ov,
for_each_child_of_node(tree, node)
cnt++;

+ if (of_get_child_by_name(tree, "__symbols__"))
+ cnt++;
+
ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL);
if (ovinfo == NULL)
return -ENOMEM;
@@ -325,6 +409,20 @@ static int of_build_overlay_info(struct of_overlay *ov,
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;
+
+ if (!ovinfo[cnt].target) {
+ pr_err("no symbols in root of device tree.\n");
+ return -EINVAL;
+ }
+
+ cnt++;
+ }
+
/* if nothing filled, return error */
if (cnt == 0) {
kfree(ovinfo);
--
Frank Rowand <[email protected]>

2017-07-19 16:26:23

by Frank Rowand

[permalink] [raw]
Subject: [PATCH v4 2/3] of: overlay: correctly apply overlay node with unit-address

From: Frank Rowand <[email protected]>

Correct existing node name detection when overlay node name has
a unit-address.

Expected test result is overlay will update the nodes and properties
for /testcase-data-2/fairway-1/ride@100/ after this commit.

Before this commit:

Console error message near end of unittest:
OF: Duplicate name in fairway-1, renamed to "ride@100#1"

$ cd /proc/device-tree/testcase-data-2/fairway-1/
$ # extra node: ride@100#1
$ ls
#address-cells linux,phandle phandle ride@200
#size-cells name ride@100 status
compatible orientation ride@100#1
$ cd /proc/device-tree/testcase-data-2/fairway-1/ride@100/
$ ls track@30/incline-up
ls: track@30/incline-up: No such file or directory
$ ls track@40/incline-up
ls: track@40/incline-up: No such file or directory

After this commit:

Console error message no longer occurs

$ cd /proc/device-tree/testcase-data-2/fairway-1/
$ # no extra node: ride@100#1
$ ls
#address-cells compatible name phandle ride@200
#size-cells linux,phandle orientation ride@100 status
$ cd /proc/device-tree/testcase-data-2/fairway-1/ride@100/
$ ls track@30/incline-up
track@30/incline-up
$ ls track@40/incline-up
track@40/incline-up

Signed-off-by: Frank Rowand <[email protected]>
---
drivers/of/overlay.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index c0e4ee1cd1ba..bd3c32f2d411 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -130,7 +130,10 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
return -ENOMEM;

/* NOTE: Multiple mods of created nodes not supported */
- tchild = of_get_child_by_name(target, cname);
+ 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)
--
Frank Rowand <[email protected]>

2017-07-20 14:48:10

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] of: overlay: load overlay symbols into live device tree

On Wed, Jul 19, 2017 at 11:25 AM, <[email protected]> wrote:
> From: Frank Rowand <[email protected]>
>
> Symbols in a loaded overlay are not currently available to subsequently
> loaded overlays because the properties in the overlay's __symbols__
> node are not loaded into the live device tree.
>
> Patch 1 is unittests to test patches 2 and 3.
>
> Patch 2 fixes a problem discovered while developing patch 3. If
> a node name in an overlay has a unit-address then the overlay
> code does not correctly match the node name against an existing
> node in the live tree.
>
> Patch 3 adds the properties in an overlay's __symbol__ node to
> the overlay changeset.
>
> changes since v3:
> - fix make W=2 warnings in overlay_base.dts and overlay.dts
> - update the test results in the patch comments to match the
> .dts changes
>
> changes since v2:
> - test on 4.13-rc1
> - remove redundant comments from patch headers of patch 0 and patch 1
> - guard make of overlay .dtb files with CONFIG_OF_OVERLAY
> - guard unittest.c references to overlay .dtb files with
> CONFIG_OF_OVERLAY
>
> changes since v1:
> - patch 2: Use for_each_child_of_node() instead of open coding,
> which allowed removing the new function child_by_full_name().
>
>
>
> Frank Rowand (3):
> of: overlay: add overlay unittest data for node names and symbols
> of: overlay: correctly apply overlay node with unit-address
> of: overlay: add overlay symbols to live device tree

Series applied.

Rob