]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Feb 2019 08:52:08 +0000 (09:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Feb 2019 08:52:08 +0000 (09:52 +0100)
added patches:
of-convert-to-using-pofn-instead-of-device_node.name.patch
of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch
of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch
of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch
of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch

queue-4.19/of-convert-to-using-pofn-instead-of-device_node.name.patch [new file with mode: 0644]
queue-4.19/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch [new file with mode: 0644]
queue-4.19/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch [new file with mode: 0644]
queue-4.19/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch [new file with mode: 0644]
queue-4.19/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/of-convert-to-using-pofn-instead-of-device_node.name.patch b/queue-4.19/of-convert-to-using-pofn-instead-of-device_node.name.patch
new file mode 100644 (file)
index 0000000..39d64df
--- /dev/null
@@ -0,0 +1,169 @@
+From a613b26a50136ae90ab13943afe90bcbd34adb44 Mon Sep 17 00:00:00 2001
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 27 Aug 2018 20:00:19 -0500
+Subject: of: Convert to using %pOFn instead of device_node.name
+
+From: Rob Herring <robh@kernel.org>
+
+commit a613b26a50136ae90ab13943afe90bcbd34adb44 upstream.
+
+In preparation to remove the node name pointer from struct device_node,
+convert printf users to use the %pOFn format specifier.
+
+Reviewed-by: Frank Rowand <frank.rowand@sony.com>
+Cc: Andrew Lunn <andrew@lunn.ch>
+Cc: Florian Fainelli <f.fainelli@gmail.com>
+Cc: netdev@vger.kernel.org
+Signed-off-by: Rob Herring <robh@kernel.org>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/device.c   |    5 +++--
+ drivers/of/of_mdio.c  |   12 ++++++------
+ drivers/of/of_numa.c  |    4 ++--
+ drivers/of/overlay.c  |    4 ++--
+ drivers/of/platform.c |    8 ++++----
+ drivers/of/unittest.c |   12 ++++++------
+ 6 files changed, 23 insertions(+), 22 deletions(-)
+
+--- a/drivers/of/device.c
++++ b/drivers/of/device.c
+@@ -221,7 +221,8 @@ static ssize_t of_device_get_modalias(st
+               return -ENODEV;
+       /* Name & Type */
+-      csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name,
++      /* %p eats all alphanum characters, so %c must be used here */
++      csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
+                        dev->of_node->type);
+       tsize = csize;
+       len -= csize;
+@@ -300,7 +301,7 @@ void of_device_uevent(struct device *dev
+       if ((!dev) || (!dev->of_node))
+               return;
+-      add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
++      add_uevent_var(env, "OF_NAME=%pOFn", dev->of_node);
+       add_uevent_var(env, "OF_FULLNAME=%pOF", dev->of_node);
+       if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
+               add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
+--- a/drivers/of/of_mdio.c
++++ b/drivers/of/of_mdio.c
+@@ -97,8 +97,8 @@ static int of_mdiobus_register_phy(struc
+               return rc;
+       }
+-      dev_dbg(&mdio->dev, "registered phy %s at address %i\n",
+-              child->name, addr);
++      dev_dbg(&mdio->dev, "registered phy %pOFn at address %i\n",
++              child, addr);
+       return 0;
+ }
+@@ -127,8 +127,8 @@ static int of_mdiobus_register_device(st
+               return rc;
+       }
+-      dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n",
+-              child->name, addr);
++      dev_dbg(&mdio->dev, "registered mdio device %pOFn at address %i\n",
++              child, addr);
+       return 0;
+ }
+@@ -263,8 +263,8 @@ int of_mdiobus_register(struct mii_bus *
+                               continue;
+                       /* be noisy to encourage people to set reg property */
+-                      dev_info(&mdio->dev, "scan phy %s at address %i\n",
+-                               child->name, addr);
++                      dev_info(&mdio->dev, "scan phy %pOFn at address %i\n",
++                               child, addr);
+                       if (of_mdiobus_child_is_phy(child)) {
+                               rc = of_mdiobus_register_phy(mdio, child, addr);
+--- a/drivers/of/of_numa.c
++++ b/drivers/of/of_numa.c
+@@ -168,8 +168,8 @@ int of_node_to_nid(struct device_node *d
+               np = of_get_next_parent(np);
+       }
+       if (np && r)
+-              pr_warn("Invalid \"numa-node-id\" property in node %s\n",
+-                      np->name);
++              pr_warn("Invalid \"numa-node-id\" property in node %pOFn\n",
++                      np);
+       of_node_put(np);
+       /*
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -427,8 +427,8 @@ static int build_changeset_next_level(st
+       for_each_child_of_node(overlay_node, child) {
+               ret = add_changeset_node(ovcs, target_node, child);
+               if (ret) {
+-                      pr_debug("Failed to apply node @%pOF/%s, err=%d\n",
+-                               target_node, child->name, ret);
++                      pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n",
++                               target_node, child, ret);
+                       of_node_put(child);
+                       return ret;
+               }
+--- a/drivers/of/platform.c
++++ b/drivers/of/platform.c
+@@ -91,8 +91,8 @@ static void of_device_make_bus_id(struct
+                */
+               reg = of_get_property(node, "reg", NULL);
+               if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
+-                      dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
+-                                   (unsigned long long)addr, node->name,
++                      dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn",
++                                   (unsigned long long)addr, node,
+                                    dev_name(dev));
+                       return;
+               }
+@@ -142,8 +142,8 @@ struct platform_device *of_device_alloc(
+                       WARN_ON(rc);
+               }
+               if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
+-                      pr_debug("not all legacy IRQ resources mapped for %s\n",
+-                               np->name);
++                      pr_debug("not all legacy IRQ resources mapped for %pOFn\n",
++                               np);
+       }
+       dev->dev.of_node = of_node_get(np);
+--- a/drivers/of/unittest.c
++++ b/drivers/of/unittest.c
+@@ -212,8 +212,8 @@ static int __init of_unittest_check_node
+       for_each_child_of_node(np, child) {
+               if (child->parent != np) {
+-                      pr_err("Child node %s links to wrong parent %s\n",
+-                               child->name, np->name);
++                      pr_err("Child node %pOFn links to wrong parent %pOFn\n",
++                               child, np);
+                       rc = -EINVAL;
+                       goto put_child;
+               }
+@@ -1046,16 +1046,16 @@ static void __init of_unittest_platform_
+       for_each_child_of_node(np, child) {
+               for_each_child_of_node(child, grandchild)
+                       unittest(of_find_device_by_node(grandchild),
+-                               "Could not create device for node '%s'\n",
+-                               grandchild->name);
++                               "Could not create device for node '%pOFn'\n",
++                               grandchild);
+       }
+       of_platform_depopulate(&test_bus->dev);
+       for_each_child_of_node(np, child) {
+               for_each_child_of_node(child, grandchild)
+                       unittest(!of_find_device_by_node(grandchild),
+-                               "device didn't get destroyed '%s'\n",
+-                               grandchild->name);
++                               "device didn't get destroyed '%pOFn'\n",
++                               grandchild);
+       }
+       platform_device_unregister(test_bus);
diff --git a/queue-4.19/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch b/queue-4.19/of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch
new file mode 100644 (file)
index 0000000..29f2914
--- /dev/null
@@ -0,0 +1,66 @@
+From 5b2c2f5a0ea3a43e0dee78059e34c7cb54136dcc Mon Sep 17 00:00:00 2001
+From: Frank Rowand <frank.rowand@sony.com>
+Date: Thu, 4 Oct 2018 20:26:05 -0700
+Subject: of: overlay: add missing of_node_get() in __of_attach_node_sysfs
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+commit 5b2c2f5a0ea3a43e0dee78059e34c7cb54136dcc upstream.
+
+There is a matching of_node_put() in __of_detach_node_sysfs()
+
+Remove misleading comment from function header comment for
+of_detach_node().
+
+This patch may result in memory leaks from code that directly calls
+the dynamic node add and delete functions directly instead of
+using changesets.
+
+This commit should result in powerpc systems that dynamically
+allocate a node, then later deallocate the node to have a
+memory leak when the node is deallocated.
+
+The next commit will fix the leak.
+
+Tested-by: Alan Tull <atull@kernel.org>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/dynamic.c |    3 ---
+ drivers/of/kobj.c    |    4 +++-
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/of/dynamic.c
++++ b/drivers/of/dynamic.c
+@@ -275,9 +275,6 @@ void __of_detach_node(struct device_node
+ /**
+  * of_detach_node() - "Unplug" a node from the device tree.
+- *
+- * The caller must hold a reference to the node.  The memory associated with
+- * the node is not freed until its refcount goes to zero.
+  */
+ int of_detach_node(struct device_node *np)
+ {
+--- a/drivers/of/kobj.c
++++ b/drivers/of/kobj.c
+@@ -133,6 +133,9 @@ int __of_attach_node_sysfs(struct device
+       }
+       if (!name)
+               return -ENOMEM;
++
++      of_node_get(np);
++
+       rc = kobject_add(&np->kobj, parent, "%s", name);
+       kfree(name);
+       if (rc)
+@@ -159,6 +162,5 @@ void __of_detach_node_sysfs(struct devic
+               kobject_del(&np->kobj);
+       }
+-      /* finally remove the kobj_init ref */
+       of_node_put(np);
+ }
diff --git a/queue-4.19/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch b/queue-4.19/of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch
new file mode 100644 (file)
index 0000000..da40f43
--- /dev/null
@@ -0,0 +1,114 @@
+From 144552c786925314c1e7cb8f91a71dae1aca8798 Mon Sep 17 00:00:00 2001
+From: Frank Rowand <frank.rowand@sony.com>
+Date: Thu, 4 Oct 2018 20:24:17 -0700
+Subject: of: overlay: add tests to validate kfrees from overlay removal
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+commit 144552c786925314c1e7cb8f91a71dae1aca8798 upstream.
+
+Add checks:
+  - attempted kfree due to refcount reaching zero before overlay
+    is removed
+  - properties linked to an overlay node when the node is removed
+  - node refcount > one during node removal in a changeset destroy,
+    if the node was created by the changeset
+
+After applying this patch, several validation warnings will be
+reported from the devicetree unittest during boot due to
+pre-existing devicetree bugs. The warnings will be similar to:
+
+  OF: ERROR: of_node_release(), unexpected properties in /testcase-data/overlay-node/test-bus/test-unittest11
+  OF: ERROR: memory leak, expected refcount 1 instead of 2, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node /testcase-data-2/substation@100/
+  hvac-medium-2
+
+Tested-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/dynamic.c |   29 +++++++++++++++++++++++++++++
+ drivers/of/overlay.c |    1 +
+ include/linux/of.h   |   15 ++++++++++-----
+ 3 files changed, 40 insertions(+), 5 deletions(-)
+
+--- a/drivers/of/dynamic.c
++++ b/drivers/of/dynamic.c
+@@ -333,6 +333,25 @@ void of_node_release(struct kobject *kob
+       if (!of_node_check_flag(node, OF_DYNAMIC))
+               return;
++      if (of_node_check_flag(node, OF_OVERLAY)) {
++
++              if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {
++                      /* premature refcount of zero, do not free memory */
++                      pr_err("ERROR: memory leak before free overlay changeset,  %pOF\n",
++                             node);
++                      return;
++              }
++
++              /*
++               * If node->properties non-empty then properties were added
++               * to this node either by different overlay that has not
++               * yet been removed, or by a non-overlay mechanism.
++               */
++              if (node->properties)
++                      pr_err("ERROR: %s(), unexpected properties in %pOF\n",
++                             __func__, node);
++      }
++
+       property_list_free(node->properties);
+       property_list_free(node->deadprops);
+@@ -437,6 +456,16 @@ struct device_node *__of_node_dup(const
+ static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
+ {
++      if (ce->action == OF_RECONFIG_ATTACH_NODE &&
++          of_node_check_flag(ce->np, OF_OVERLAY)) {
++              if (kref_read(&ce->np->kobj.kref) > 1) {
++                      pr_err("ERROR: memory leak, expected refcount 1 instead of %d, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node %pOF\n",
++                             kref_read(&ce->np->kobj.kref), ce->np);
++              } else {
++                      of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);
++              }
++      }
++
+       of_node_put(ce->np);
+       list_del(&ce->node);
+       kfree(ce);
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -373,6 +373,7 @@ static int add_changeset_node(struct ove
+                       return -ENOMEM;
+               tchild->parent = target_node;
++              of_node_set_flag(tchild, OF_OVERLAY);
+               ret = of_changeset_attach_node(&ovcs->cset, tchild);
+               if (ret)
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -138,11 +138,16 @@ extern struct device_node *of_aliases;
+ extern struct device_node *of_stdout;
+ extern raw_spinlock_t devtree_lock;
+-/* flag descriptions (need to be visible even when !CONFIG_OF) */
+-#define OF_DYNAMIC    1 /* node and properties were allocated via kmalloc */
+-#define OF_DETACHED   2 /* node has been detached from the device tree */
+-#define OF_POPULATED  3 /* device already created for the node */
+-#define OF_POPULATED_BUS      4 /* of_platform_populate recursed to children of this node */
++/*
++ * struct device_node flag descriptions
++ * (need to be visible even when !CONFIG_OF)
++ */
++#define OF_DYNAMIC            1 /* (and properties) allocated via kmalloc */
++#define OF_DETACHED           2 /* detached from the device tree */
++#define OF_POPULATED          3 /* device already created */
++#define OF_POPULATED_BUS      4 /* platform bus created for children */
++#define OF_OVERLAY            5 /* allocated for an overlay */
++#define OF_OVERLAY_FREE_CSET  6 /* in overlay cset being freed */
+ #define OF_BAD_ADDR   ((u64)-1)
diff --git a/queue-4.19/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch b/queue-4.19/of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch
new file mode 100644 (file)
index 0000000..4a24631
--- /dev/null
@@ -0,0 +1,48 @@
+From 8814dc46bd9e347d4de55ec5bf8f16ea54470499 Mon Sep 17 00:00:00 2001
+From: Frank Rowand <frank.rowand@sony.com>
+Date: Thu, 4 Oct 2018 20:29:01 -0700
+Subject: of: overlay: do not duplicate properties from overlay for new nodes
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+commit 8814dc46bd9e347d4de55ec5bf8f16ea54470499 upstream.
+
+When allocating a new node, add_changeset_node() was duplicating the
+properties from the respective node in the overlay instead of
+allocating a node with no properties.
+
+When this patch is applied the errors reported by the devictree
+unittest from patch "of: overlay: add tests to validate kfrees from
+overlay removal" will no longer occur.  These error messages are of
+the form:
+
+   "OF: ERROR: ..."
+
+and the unittest results will change from:
+
+   ### dt-test ### end of unittest - 203 passed, 7 failed
+
+to
+
+   ### dt-test ### end of unittest - 210 passed, 0 failed
+
+Tested-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/overlay.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -393,7 +393,7 @@ static int add_changeset_node(struct ove
+                       break;
+       if (!tchild) {
+-              tchild = __of_node_dup(node, node_kbasename);
++              tchild = __of_node_dup(NULL, node_kbasename);
+               if (!tchild)
+                       return -ENOMEM;
diff --git a/queue-4.19/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch b/queue-4.19/of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch
new file mode 100644 (file)
index 0000000..0de3dc6
--- /dev/null
@@ -0,0 +1,329 @@
+From 6b4955ba7bc05e40c8c41071cc121bc26ca65277 Mon Sep 17 00:00:00 2001
+From: Frank Rowand <frank.rowand@sony.com>
+Date: Thu, 4 Oct 2018 20:28:08 -0700
+Subject: of: overlay: use prop add changeset entry for property in new nodes
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+commit 6b4955ba7bc05e40c8c41071cc121bc26ca65277 upstream.
+
+The changeset entry 'update property' was used for new properties in
+an overlay instead of 'add property'.
+
+The decision of whether to use 'update property' was based on whether
+the property already exists in the subtree where the node is being
+spliced into.  At the top level of creating a changeset describing the
+overlay, the target node is in the live devicetree, so checking whether
+the property exists in the target node returns the correct result.
+As soon as the changeset creation algorithm recurses into a new node,
+the target is no longer in the live devicetree, but is instead in the
+detached overlay tree, thus all properties are incorrectly found to
+already exist in the target.
+
+This fix will expose another devicetree bug that will be fixed
+in the following patch in the series.
+
+When this patch is applied the errors reported by the devictree
+unittest will change, and the unittest results will change from:
+
+   ### dt-test ### end of unittest - 210 passed, 0 failed
+
+to
+
+   ### dt-test ### end of unittest - 203 passed, 7 failed
+
+Tested-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/of/overlay.c |  112 +++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 74 insertions(+), 38 deletions(-)
+
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -24,6 +24,26 @@
+ #include "of_private.h"
+ /**
++ * struct target - info about current target node as recursing through overlay
++ * @np:                       node where current level of overlay will be applied
++ * @in_livetree:      @np is a node in the live devicetree
++ *
++ * Used in the algorithm to create the portion of a changeset that describes
++ * an overlay fragment, which is a devicetree subtree.  Initially @np is a node
++ * in the live devicetree where the overlay subtree is targeted to be grafted
++ * into.  When recursing to the next level of the overlay subtree, the target
++ * also recurses to the next level of the live devicetree, as long as overlay
++ * subtree node also exists in the live devicetree.  When a node in the overlay
++ * subtree does not exist at the same level in the live devicetree, target->np
++ * points to a newly allocated node, and all subsequent targets in the subtree
++ * will be newly allocated nodes.
++ */
++struct target {
++      struct device_node *np;
++      bool in_livetree;
++};
++
++/**
+  * struct fragment - info about fragment nodes in overlay expanded device tree
+  * @target:   target of the overlay operation
+  * @overlay:  pointer to the __overlay__ node
+@@ -72,8 +92,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);
++              struct target *target, const struct device_node *overlay_node);
+ /*
+  * of_resolve_phandles() finds the largest phandle in the live tree.
+@@ -257,14 +276,17 @@ err_free_target_path:
+ /**
+  * add_changeset_property() - add @overlay_prop to overlay changeset
+  * @ovcs:             overlay changeset
+- * @target_node:      where to place @overlay_prop in live tree
++ * @target:           where @overlay_prop will be placed
+  * @overlay_prop:     property to add or update, from overlay tree
+  * @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
++ * If @overlay_prop does not already exist in live devicetree, add changeset
++ * entry to add @overlay_prop in @target, else add changeset entry to update
+  * value of @overlay_prop.
+  *
++ * @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).
+  *
+  * Update of property in symbols node is not allowed.
+@@ -273,20 +295,22 @@ err_free_target_path:
+  * invalid @overlay.
+  */
+ static int add_changeset_property(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
+-              struct property *overlay_prop,
++              struct target *target, struct property *overlay_prop,
+               bool is_symbols_prop)
+ {
+       struct property *new_prop = NULL, *prop;
+       int ret = 0;
+-      prop = of_find_property(target_node, overlay_prop->name, NULL);
+-
+       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 (target->in_livetree)
++              prop = of_find_property(target->np, overlay_prop->name, NULL);
++      else
++              prop = NULL;
++
+       if (is_symbols_prop) {
+               if (prop)
+                       return -EINVAL;
+@@ -299,10 +323,10 @@ static int add_changeset_property(struct
+               return -ENOMEM;
+       if (!prop)
+-              ret = of_changeset_add_property(&ovcs->cset, target_node,
++              ret = of_changeset_add_property(&ovcs->cset, target->np,
+                                               new_prop);
+       else
+-              ret = of_changeset_update_property(&ovcs->cset, target_node,
++              ret = of_changeset_update_property(&ovcs->cset, target->np,
+                                                  new_prop);
+       if (ret) {
+@@ -315,14 +339,14 @@ static int add_changeset_property(struct
+ /**
+  * 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
++ * @ovcs:     overlay changeset
++ * @target:   where @node will be placed in live tree or changeset
++ * @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 does not already exist in @target, add changeset entry
++ * to add @node in @target.
+  *
+- * If @node already exists in @target_node, and the existing node has
++ * If @node already exists in @target, 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
+@@ -355,15 +379,16 @@ static int add_changeset_property(struct
+  * invalid @overlay.
+  */
+ static int add_changeset_node(struct overlay_changeset *ovcs,
+-              struct device_node *target_node, struct device_node *node)
++              struct target *target, struct device_node *node)
+ {
+       const char *node_kbasename;
+       struct device_node *tchild;
++      struct target target_child;
+       int ret = 0;
+       node_kbasename = kbasename(node->full_name);
+-      for_each_child_of_node(target_node, tchild)
++      for_each_child_of_node(target->np, tchild)
+               if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
+                       break;
+@@ -372,22 +397,28 @@ static int add_changeset_node(struct ove
+               if (!tchild)
+                       return -ENOMEM;
+-              tchild->parent = target_node;
++              tchild->parent = target->np;
+               of_node_set_flag(tchild, OF_OVERLAY);
+               ret = of_changeset_attach_node(&ovcs->cset, tchild);
+               if (ret)
+                       return ret;
+-              ret = build_changeset_next_level(ovcs, tchild, node);
++              target_child.np = tchild;
++              target_child.in_livetree = false;
++
++              ret = build_changeset_next_level(ovcs, &target_child, node);
+               of_node_put(tchild);
+               return ret;
+       }
+-      if (node->phandle && tchild->phandle)
++      if (node->phandle && tchild->phandle) {
+               ret = -EINVAL;
+-      else
+-              ret = build_changeset_next_level(ovcs, tchild, node);
++      } else {
++              target_child.np = tchild;
++              target_child.in_livetree = target->in_livetree;
++              ret = build_changeset_next_level(ovcs, &target_child, node);
++      }
+       of_node_put(tchild);
+       return ret;
+@@ -396,7 +427,7 @@ static int add_changeset_node(struct ove
+ /**
+  * build_changeset_next_level() - add level of overlay changeset
+  * @ovcs:             overlay changeset
+- * @target_node:      where to place @overlay_node in live tree
++ * @target:           where to place @overlay_node in live tree
+  * @overlay_node:     node from within an overlay device tree fragment
+  *
+  * Add the properties (if any) and nodes (if any) from @overlay_node to the
+@@ -409,27 +440,26 @@ static int add_changeset_node(struct ove
+  * invalid @overlay_node.
+  */
+ static int build_changeset_next_level(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
+-              const struct device_node *overlay_node)
++              struct target *target, 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, 0);
++              ret = add_changeset_property(ovcs, target, prop, 0);
+               if (ret) {
+                       pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
+-                               target_node, prop->name, ret);
++                               target->np, prop->name, ret);
+                       return ret;
+               }
+       }
+       for_each_child_of_node(overlay_node, child) {
+-              ret = add_changeset_node(ovcs, target_node, child);
++              ret = add_changeset_node(ovcs, target, child);
+               if (ret) {
+                       pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n",
+-                               target_node, child, ret);
++                               target->np, child, ret);
+                       of_node_put(child);
+                       return ret;
+               }
+@@ -442,17 +472,17 @@ static int build_changeset_next_level(st
+  * 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,
++              struct target *target,
+               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);
++              ret = add_changeset_property(ovcs, target, prop, 1);
+               if (ret) {
+                       pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
+-                               target_node, prop->name, ret);
++                               target->np, prop->name, ret);
+                       return ret;
+               }
+       }
+@@ -475,6 +505,7 @@ static int build_changeset_symbols_node(
+ static int build_changeset(struct overlay_changeset *ovcs)
+ {
+       struct fragment *fragment;
++      struct target target;
+       int fragments_count, i, ret;
+       /*
+@@ -489,7 +520,9 @@ static int build_changeset(struct overla
+       for (i = 0; i < fragments_count; i++) {
+               fragment = &ovcs->fragments[i];
+-              ret = build_changeset_next_level(ovcs, fragment->target,
++              target.np = fragment->target;
++              target.in_livetree = true;
++              ret = build_changeset_next_level(ovcs, &target,
+                                                fragment->overlay);
+               if (ret) {
+                       pr_debug("apply failed '%pOF'\n", fragment->target);
+@@ -499,7 +532,10 @@ static int build_changeset(struct overla
+       if (ovcs->symbols_fragment) {
+               fragment = &ovcs->fragments[ovcs->count - 1];
+-              ret = build_changeset_symbols_node(ovcs, fragment->target,
++
++              target.np = fragment->target;
++              target.in_livetree = true;
++              ret = build_changeset_symbols_node(ovcs, &target,
+                                                  fragment->overlay);
+               if (ret) {
+                       pr_debug("apply failed '%pOF'\n", fragment->target);
+@@ -517,7 +553,7 @@ static int build_changeset(struct overla
+  * 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)
++static struct device_node *find_target(struct device_node *info_node)
+ {
+       struct device_node *node;
+       const char *path;
+@@ -623,7 +659,7 @@ static int init_overlay_changeset(struct
+               fragment = &fragments[cnt];
+               fragment->overlay = overlay_node;
+-              fragment->target = find_target_node(node);
++              fragment->target = find_target(node);
+               if (!fragment->target) {
+                       of_node_put(fragment->overlay);
+                       ret = -EINVAL;
index b696b1e64bbd79fe766eed5c38f3b84b31360349..7b464820731415aa299186f651438f56b42d1e69 100644 (file)
@@ -65,3 +65,8 @@ mm-memory_hotplug-fix-scan_movable_pages-for-gigantic-hugepages.patch
 mm-oom-fix-use-after-free-in-oom_kill_process.patch
 mm-hwpoison-use-do_send_sig_info-instead-of-force_sig.patch
 mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch
+of-convert-to-using-pofn-instead-of-device_node.name.patch
+of-overlay-add-tests-to-validate-kfrees-from-overlay-removal.patch
+of-overlay-add-missing-of_node_get-in-__of_attach_node_sysfs.patch
+of-overlay-use-prop-add-changeset-entry-for-property-in-new-nodes.patch
+of-overlay-do-not-duplicate-properties-from-overlay-for-new-nodes.patch