| From f96278810150fc39085d1872e5b39ea06366d03e Mon Sep 17 00:00:00 2001 |
| From: Frank Rowand <frank.rowand@sony.com> |
| Date: Fri, 12 Oct 2018 19:21:16 -0700 |
| Subject: of: overlay: set node fields from properties when add new overlay node |
| |
| From: Frank Rowand <frank.rowand@sony.com> |
| |
| commit f96278810150fc39085d1872e5b39ea06366d03e upstream. |
| |
| Overlay nodes added by add_changeset_node() do not have the node |
| fields name, phandle, and type set. |
| |
| The node passed to __of_attach_node() when the add node changeset |
| entry is processed does not contain any properties. The node's |
| properties are located in add property changeset entries that will |
| be processed after the add node changeset is applied. |
| |
| Set the node's fields in the node contained in the add node |
| changeset entry and do not set them to incorrect values in |
| add_changeset_node(). |
| |
| A visible symptom that is fixed by this patch is the names of nodes |
| added by overlays that have an entry in /sys/bus/platform/drivers/*/ |
| will contain the unit-address but the node-name will be <NULL>, for |
| example, "fc4ab000.<NULL>". After applying the patch the name, in |
| this example, for node restart@fc4ab000 is "fc4ab000.restart". |
| |
| Tested-by: Alan Tull <atull@kernel.org> |
| Signed-off-by: Frank Rowand <frank.rowand@sony.com> |
| Cc: Phil Elwell <phil@raspberrypi.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/of/dynamic.c | 25 +++++++++++++++++-------- |
| drivers/of/overlay.c | 29 ++++++++++++++++++++++++----- |
| 2 files changed, 41 insertions(+), 13 deletions(-) |
| |
| --- a/drivers/of/dynamic.c |
| +++ b/drivers/of/dynamic.c |
| @@ -205,15 +205,24 @@ static void __of_attach_node(struct devi |
| const __be32 *phandle; |
| int sz; |
| |
| - np->name = __of_get_property(np, "name", NULL) ? : "<NULL>"; |
| - np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>"; |
| + if (!of_node_check_flag(np, OF_OVERLAY)) { |
| + np->name = __of_get_property(np, "name", NULL); |
| + np->type = __of_get_property(np, "device_type", NULL); |
| + if (!np->name) |
| + np->name = "<NULL>"; |
| + if (!np->type) |
| + np->type = "<NULL>"; |
| |
| - phandle = __of_get_property(np, "phandle", &sz); |
| - if (!phandle) |
| - phandle = __of_get_property(np, "linux,phandle", &sz); |
| - if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) |
| - phandle = __of_get_property(np, "ibm,phandle", &sz); |
| - np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0; |
| + phandle = __of_get_property(np, "phandle", &sz); |
| + if (!phandle) |
| + phandle = __of_get_property(np, "linux,phandle", &sz); |
| + if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) |
| + phandle = __of_get_property(np, "ibm,phandle", &sz); |
| + if (phandle && (sz >= 4)) |
| + np->phandle = be32_to_cpup(phandle); |
| + else |
| + np->phandle = 0; |
| + } |
| |
| np->child = NULL; |
| np->sibling = np->parent->child; |
| --- a/drivers/of/overlay.c |
| +++ b/drivers/of/overlay.c |
| @@ -307,10 +307,11 @@ static int add_changeset_property(struct |
| 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") || |
| - !of_prop_cmp(overlay_prop->name, "linux,phandle")) |
| - return 0; |
| + if (target->in_livetree) |
| + 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); |
| @@ -330,6 +331,10 @@ static int add_changeset_property(struct |
| |
| if (!prop) { |
| check_for_non_overlay_node = true; |
| + if (!target->in_livetree) { |
| + new_prop->next = target->np->deadprops; |
| + target->np->deadprops = new_prop; |
| + } |
| ret = of_changeset_add_property(&ovcs->cset, target->np, |
| new_prop); |
| } else if (!of_prop_cmp(prop->name, "#address-cells")) { |
| @@ -408,9 +413,10 @@ static int add_changeset_node(struct ove |
| struct target *target, struct device_node *node) |
| { |
| const char *node_kbasename; |
| + const __be32 *phandle; |
| struct device_node *tchild; |
| struct target target_child; |
| - int ret = 0; |
| + int ret = 0, size; |
| |
| node_kbasename = kbasename(node->full_name); |
| |
| @@ -424,6 +430,19 @@ static int add_changeset_node(struct ove |
| return -ENOMEM; |
| |
| tchild->parent = target->np; |
| + tchild->name = __of_get_property(node, "name", NULL); |
| + tchild->type = __of_get_property(node, "device_type", NULL); |
| + |
| + if (!tchild->name) |
| + tchild->name = "<NULL>"; |
| + if (!tchild->type) |
| + tchild->type = "<NULL>"; |
| + |
| + /* ignore obsolete "linux,phandle" */ |
| + phandle = __of_get_property(node, "phandle", &size); |
| + if (phandle && (size == 4)) |
| + tchild->phandle = be32_to_cpup(phandle); |
| + |
| of_node_set_flag(tchild, OF_OVERLAY); |
| |
| ret = of_changeset_attach_node(&ovcs->cset, tchild); |