summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@sony.com>2018-10-04 20:32:04 -0700
committerFrank Rowand <frank.rowand@sony.com>2018-11-08 22:11:32 -0800
commit6f75118800acf77f8ad6afec61ca1b2349ade371 (patch)
treec8c46a2f76a8ae4cab60f79ad6575deef7334787 /drivers
parent81225ea682f45629a66309636482b7c9bc2dcec1 (diff)
downloadlinux-6f75118800acf77f8ad6afec61ca1b2349ade371.tar.bz2
of: overlay: validate overlay properties #address-cells and #size-cells
If overlay properties #address-cells or #size-cells are already in the live devicetree for any given node, then the values in the overlay must match the values in the live tree. If the properties are already in the live tree then there is no need to create a changeset entry to add them since they must have the same value. This reduces the memory used by the changeset and eliminates a possible memory leak. Tested-by: Alan Tull <atull@kernel.org> Signed-off-by: Frank Rowand <frank.rowand@sony.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/overlay.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 15be3da34fef..72bf00adb9c8 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -287,7 +287,12 @@ err_free_target_path:
* @target may be either in the live devicetree or in a new subtree that
* is contained in the changeset.
*
- * Some special properties are not updated (no error returned).
+ * Some special properties are not added or updated (no error returned):
+ * "name", "phandle", "linux,phandle".
+ *
+ * Properties "#address-cells" and "#size-cells" are not updated if they
+ * are already in the live tree, but if present in the live tree, the values
+ * in the overlay must match the values in the live tree.
*
* Update of property in symbols node is not allowed.
*
@@ -300,6 +305,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
{
struct property *new_prop = NULL, *prop;
int ret = 0;
+ bool check_for_non_overlay_node = false;
if (!of_prop_cmp(overlay_prop->name, "name") ||
!of_prop_cmp(overlay_prop->name, "phandle") ||
@@ -322,12 +328,32 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
if (!new_prop)
return -ENOMEM;
- if (!prop)
+ if (!prop) {
+ check_for_non_overlay_node = true;
ret = of_changeset_add_property(&ovcs->cset, target->np,
new_prop);
- else
+ } else if (!of_prop_cmp(prop->name, "#address-cells")) {
+ if (!of_prop_val_eq(prop, new_prop)) {
+ pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
+ target->np);
+ ret = -EINVAL;
+ }
+ } else if (!of_prop_cmp(prop->name, "#size-cells")) {
+ if (!of_prop_val_eq(prop, new_prop)) {
+ pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
+ target->np);
+ ret = -EINVAL;
+ }
+ } else {
+ check_for_non_overlay_node = true;
ret = of_changeset_update_property(&ovcs->cset, target->np,
new_prop);
+ }
+
+ if (check_for_non_overlay_node &&
+ !of_node_check_flag(target->np, OF_OVERLAY))
+ pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
+ target->np, new_prop->name);
if (ret) {
kfree(new_prop->name);