aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@sony.com>2017-10-17 19:36:31 -0400
committerRob Herring <robh@kernel.org>2017-10-17 21:47:37 -0400
commite0a58f3e08d4b7fa8e2a4075c522f1a98c9e4cab (patch)
tree451e9c437fe1cfd801532eb356932fa39ad29ca1
parent3912b7917ab78d75b32bec8d297ac3c46b1b2a44 (diff)
of: overlay: remove a dependency on device node full_name
The "%pOF" printf format was recently added to print the full name of a device tree node, with the intent of changing the node full_name field to contain only the node name instead of the full path of the node. dup_and_fixup_symbol_prop() duplicates a property from the "/__symbols__" node of an overlay device tree. The value of each duplicated property must be fixed up to include the full path of a node in the live device tree. The current code uses the node's full_name for that purpose. Update the code to use the "%pOF" printf format to determine the node's full path. Signed-off-by: Frank Rowand <frank.rowand@sony.com> Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r--drivers/of/base.c2
-rw-r--r--drivers/of/of_private.h2
-rw-r--r--drivers/of/overlay.c90
3 files changed, 59 insertions, 35 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index b98f3adffbb0..3de07e6e82a0 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -658,7 +658,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
658} 658}
659EXPORT_SYMBOL(of_get_child_by_name); 659EXPORT_SYMBOL(of_get_child_by_name);
660 660
661static struct device_node *__of_find_node_by_path(struct device_node *parent, 661struct device_node *__of_find_node_by_path(struct device_node *parent,
662 const char *path) 662 const char *path)
663{ 663{
664 struct device_node *child; 664 struct device_node *child;
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 248730567dbe..92a9a3687446 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -110,6 +110,8 @@ extern void *__unflatten_device_tree(const void *blob,
110struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); 110struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
111__printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...); 111__printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...);
112 112
113struct device_node *__of_find_node_by_path(struct device_node *parent,
114 const char *path);
113struct device_node *__of_find_node_by_full_path(struct device_node *node, 115struct device_node *__of_find_node_by_full_path(struct device_node *node,
114 const char *path); 116 const char *path);
115 117
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 602218e07ec3..0e9aefc1ff15 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -37,6 +37,7 @@ struct fragment {
37/** 37/**
38 * struct overlay_changeset 38 * struct overlay_changeset
39 * @ovcs_list: list on which we are located 39 * @ovcs_list: list on which we are located
40 * @overlay_tree: expanded device tree that contains the fragment nodes
40 * @count: count of fragment structures 41 * @count: count of fragment structures
41 * @fragments: fragment nodes in the overlay expanded device tree 42 * @fragments: fragment nodes in the overlay expanded device tree
42 * @symbols_fragment: last element of @fragments[] is the __symbols__ node 43 * @symbols_fragment: last element of @fragments[] is the __symbols__ node
@@ -45,6 +46,7 @@ struct fragment {
45struct overlay_changeset { 46struct overlay_changeset {
46 int id; 47 int id;
47 struct list_head ovcs_list; 48 struct list_head ovcs_list;
49 struct device_node *overlay_tree;
48 int count; 50 int count;
49 struct fragment *fragments; 51 struct fragment *fragments;
50 bool symbols_fragment; 52 bool symbols_fragment;
@@ -145,12 +147,13 @@ static int overlay_notify(struct overlay_changeset *ovcs,
145} 147}
146 148
147/* 149/*
148 * The properties in the "/__symbols__" node are "symbols". 150 * The values of properties in the "/__symbols__" node are paths in
151 * the ovcs->overlay_tree. When duplicating the properties, the paths
152 * need to be adjusted to be the correct path for the live device tree.
149 * 153 *
150 * The value of properties in the "/__symbols__" node is the path of a 154 * The paths refer to a node in the subtree of a fragment node's "__overlay__"
151 * node in the subtree of a fragment node's "__overlay__" node, for 155 * node, for example "/fragment@0/__overlay__/symbol_path_tail",
152 * example "/fragment@0/__overlay__/symbol_path_tail". Symbol_path_tail 156 * where symbol_path_tail can be a single node or it may be a multi-node path.
153 * can be a single node or it may be a multi-node path.
154 * 157 *
155 * The duplicated property value will be modified by replacing the 158 * The duplicated property value will be modified by replacing the
156 * "/fragment_name/__overlay/" portion of the value with the target 159 * "/fragment_name/__overlay/" portion of the value with the target
@@ -160,59 +163,76 @@ static struct property *dup_and_fixup_symbol_prop(
160 struct overlay_changeset *ovcs, const struct property *prop) 163 struct overlay_changeset *ovcs, const struct property *prop)
161{ 164{
162 struct fragment *fragment; 165 struct fragment *fragment;
163 struct property *new; 166 struct property *new_prop;
164 const char *overlay_name; 167 struct device_node *fragment_node;
165 char *symbol_path_tail; 168 struct device_node *overlay_node;
166 char *symbol_path; 169 const char *path;
170 const char *path_tail;
167 const char *target_path; 171 const char *target_path;
168 int k; 172 int k;
169 int symbol_path_tail_len;
170 int overlay_name_len; 173 int overlay_name_len;
174 int path_len;
175 int path_tail_len;
171 int target_path_len; 176 int target_path_len;
172 177
173 if (!prop->value) 178 if (!prop->value)
174 return NULL; 179 return NULL;
175 symbol_path = prop->value; 180 if (strnlen(prop->value, prop->length) >= prop->length)
181 return NULL;
182 path = prop->value;
183 path_len = strlen(path);
176 184
177 new = kzalloc(sizeof(*new), GFP_KERNEL); 185 if (path_len < 1)
178 if (!new)
179 return NULL; 186 return NULL;
187 fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1);
188 overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/");
189 of_node_put(fragment_node);
190 of_node_put(overlay_node);
180 191
181 for (k = 0; k < ovcs->count; k++) { 192 for (k = 0; k < ovcs->count; k++) {
182 fragment = &ovcs->fragments[k]; 193 fragment = &ovcs->fragments[k];
183 overlay_name = fragment->overlay->full_name; 194 if (fragment->overlay == overlay_node)
184 overlay_name_len = strlen(overlay_name);
185 if (!strncasecmp(symbol_path, overlay_name, overlay_name_len))
186 break; 195 break;
187 } 196 }
188
189 if (k >= ovcs->count) 197 if (k >= ovcs->count)
190 goto err_free; 198 return NULL;
199
200 overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay);
191 201
192 target_path = fragment->target->full_name; 202 if (overlay_name_len > path_len)
203 return NULL;
204 path_tail = path + overlay_name_len;
205 path_tail_len = strlen(path_tail);
206
207 target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target);
208 if (!target_path)
209 return NULL;
193 target_path_len = strlen(target_path); 210 target_path_len = strlen(target_path);
194 211
195 symbol_path_tail = symbol_path + overlay_name_len; 212 new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
196 symbol_path_tail_len = strlen(symbol_path_tail); 213 if (!new_prop)
214 goto err_free_target_path;
197 215
198 new->name = kstrdup(prop->name, GFP_KERNEL); 216 new_prop->name = kstrdup(prop->name, GFP_KERNEL);
199 new->length = target_path_len + symbol_path_tail_len + 1; 217 new_prop->length = target_path_len + path_tail_len + 1;
200 new->value = kzalloc(new->length, GFP_KERNEL); 218 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
219 if (!new_prop->name || !new_prop->value)
220 goto err_free_new_prop;
201 221
202 if (!new->name || !new->value) 222 strcpy(new_prop->value, target_path);
203 goto err_free; 223 strcpy(new_prop->value + target_path_len, path_tail);
204 224
205 strcpy(new->value, target_path); 225 of_property_set_flag(new_prop, OF_DYNAMIC);
206 strcpy(new->value + target_path_len, symbol_path_tail);
207 226
208 of_property_set_flag(new, OF_DYNAMIC); 227 return new_prop;
209 228
210 return new; 229err_free_new_prop:
230 kfree(new_prop->name);
231 kfree(new_prop->value);
232 kfree(new_prop);
233err_free_target_path:
234 kfree(target_path);
211 235
212 err_free:
213 kfree(new->name);
214 kfree(new->value);
215 kfree(new);
216 return NULL; 236 return NULL;
217} 237}
218 238
@@ -519,6 +539,8 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
519 if (!of_node_is_root(tree)) 539 if (!of_node_is_root(tree))
520 pr_debug("%s() tree is not root\n", __func__); 540 pr_debug("%s() tree is not root\n", __func__);
521 541
542 ovcs->overlay_tree = tree;
543
522 INIT_LIST_HEAD(&ovcs->ovcs_list); 544 INIT_LIST_HEAD(&ovcs->ovcs_list);
523 545
524 of_changeset_init(&ovcs->cset); 546 of_changeset_init(&ovcs->cset);