]>
Commit | Line | Data |
---|---|---|
af6074fc | 1 | // SPDX-License-Identifier: GPL-2.0 |
6afc0dc3 GL |
2 | /* |
3 | * Support for dynamic device trees. | |
4 | * | |
5 | * On some platforms, the device tree can be manipulated at runtime. | |
6 | * The routines in this section support adding, removing and changing | |
7 | * device tree nodes. | |
8 | */ | |
9 | ||
606ad42a RH |
10 | #define pr_fmt(fmt) "OF: " fmt |
11 | ||
801c8b8e | 12 | #include <linux/device.h> |
6afc0dc3 GL |
13 | #include <linux/of.h> |
14 | #include <linux/spinlock.h> | |
15 | #include <linux/slab.h> | |
16 | #include <linux/string.h> | |
17 | #include <linux/proc_fs.h> | |
18 | ||
19 | #include "of_private.h" | |
20 | ||
4c2bb574 RH |
21 | static struct device_node *kobj_to_device_node(struct kobject *kobj) |
22 | { | |
23 | return container_of(kobj, struct device_node, kobj); | |
24 | } | |
25 | ||
6afc0dc3 GL |
26 | /** |
27 | * of_node_get() - Increment refcount of a node | |
28 | * @node: Node to inc refcount, NULL is supported to simplify writing of | |
29 | * callers | |
30 | * | |
8c8239c2 | 31 | * Return: The node with refcount incremented. |
6afc0dc3 GL |
32 | */ |
33 | struct device_node *of_node_get(struct device_node *node) | |
34 | { | |
35 | if (node) | |
36 | kobject_get(&node->kobj); | |
37 | return node; | |
38 | } | |
39 | EXPORT_SYMBOL(of_node_get); | |
40 | ||
41 | /** | |
42 | * of_node_put() - Decrement refcount of a node | |
43 | * @node: Node to dec refcount, NULL is supported to simplify writing of | |
44 | * callers | |
45 | */ | |
46 | void of_node_put(struct device_node *node) | |
47 | { | |
48 | if (node) | |
49 | kobject_put(&node->kobj); | |
50 | } | |
51 | EXPORT_SYMBOL(of_node_put); | |
52 | ||
6afc0dc3 GL |
53 | static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); |
54 | ||
55 | int of_reconfig_notifier_register(struct notifier_block *nb) | |
56 | { | |
57 | return blocking_notifier_chain_register(&of_reconfig_chain, nb); | |
58 | } | |
59 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); | |
60 | ||
61 | int of_reconfig_notifier_unregister(struct notifier_block *nb) | |
62 | { | |
63 | return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | |
64 | } | |
65 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | |
66 | ||
914d9d83 RH |
67 | static const char *action_names[] = { |
68 | [0] = "INVALID", | |
00aa3720 GL |
69 | [OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE", |
70 | [OF_RECONFIG_DETACH_NODE] = "DETACH_NODE", | |
71 | [OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY", | |
72 | [OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY", | |
73 | [OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY", | |
74 | }; | |
00aa3720 | 75 | |
27a02f26 RH |
76 | #define _do_print(func, prefix, action, node, prop, ...) ({ \ |
77 | func("changeset: " prefix "%-15s %pOF%s%s\n", \ | |
78 | ##__VA_ARGS__, action_names[action], node, \ | |
79 | prop ? ":" : "", prop ? prop->name : ""); \ | |
80 | }) | |
81 | #define of_changeset_action_err(...) _do_print(pr_err, __VA_ARGS__) | |
82 | #define of_changeset_action_debug(...) _do_print(pr_debug, __VA_ARGS__) | |
83 | ||
f5242e5a | 84 | int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) |
6afc0dc3 GL |
85 | { |
86 | int rc; | |
f5242e5a | 87 | struct of_reconfig_data *pr = p; |
00aa3720 | 88 | |
27a02f26 | 89 | of_changeset_action_debug("notify: ", action, pr->dn, pr->prop); |
6afc0dc3 GL |
90 | |
91 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | |
92 | return notifier_to_errno(rc); | |
93 | } | |
94 | ||
b53a2340 PA |
95 | /* |
96 | * of_reconfig_get_state_change() - Returns new state of device | |
97 | * @action - action of the of notifier | |
98 | * @arg - argument of the of notifier | |
99 | * | |
100 | * Returns the new state of a device based on the notifier used. | |
8c8239c2 | 101 | * |
30460e7e LC |
102 | * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to |
103 | * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to | |
104 | * enabled and OF_RECONFIG_NO_CHANGE on no change. | |
b53a2340 | 105 | */ |
f5242e5a | 106 | int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) |
b53a2340 | 107 | { |
f5242e5a | 108 | struct property *prop, *old_prop = NULL; |
b53a2340 PA |
109 | int is_status, status_state, old_status_state, prev_state, new_state; |
110 | ||
111 | /* figure out if a device should be created or destroyed */ | |
b53a2340 PA |
112 | switch (action) { |
113 | case OF_RECONFIG_ATTACH_NODE: | |
114 | case OF_RECONFIG_DETACH_NODE: | |
f5242e5a | 115 | prop = of_find_property(pr->dn, "status", NULL); |
b53a2340 PA |
116 | break; |
117 | case OF_RECONFIG_ADD_PROPERTY: | |
118 | case OF_RECONFIG_REMOVE_PROPERTY: | |
b53a2340 PA |
119 | prop = pr->prop; |
120 | break; | |
121 | case OF_RECONFIG_UPDATE_PROPERTY: | |
b53a2340 PA |
122 | prop = pr->prop; |
123 | old_prop = pr->old_prop; | |
124 | break; | |
125 | default: | |
126 | return OF_RECONFIG_NO_CHANGE; | |
127 | } | |
128 | ||
129 | is_status = 0; | |
130 | status_state = -1; | |
131 | old_status_state = -1; | |
132 | prev_state = -1; | |
133 | new_state = -1; | |
134 | ||
135 | if (prop && !strcmp(prop->name, "status")) { | |
136 | is_status = 1; | |
137 | status_state = !strcmp(prop->value, "okay") || | |
138 | !strcmp(prop->value, "ok"); | |
139 | if (old_prop) | |
140 | old_status_state = !strcmp(old_prop->value, "okay") || | |
141 | !strcmp(old_prop->value, "ok"); | |
142 | } | |
143 | ||
144 | switch (action) { | |
145 | case OF_RECONFIG_ATTACH_NODE: | |
146 | prev_state = 0; | |
147 | /* -1 & 0 status either missing or okay */ | |
148 | new_state = status_state != 0; | |
149 | break; | |
150 | case OF_RECONFIG_DETACH_NODE: | |
151 | /* -1 & 0 status either missing or okay */ | |
152 | prev_state = status_state != 0; | |
153 | new_state = 0; | |
154 | break; | |
155 | case OF_RECONFIG_ADD_PROPERTY: | |
156 | if (is_status) { | |
157 | /* no status property -> enabled (legacy) */ | |
158 | prev_state = 1; | |
159 | new_state = status_state; | |
160 | } | |
161 | break; | |
162 | case OF_RECONFIG_REMOVE_PROPERTY: | |
163 | if (is_status) { | |
164 | prev_state = status_state; | |
165 | /* no status property -> enabled (legacy) */ | |
166 | new_state = 1; | |
167 | } | |
168 | break; | |
169 | case OF_RECONFIG_UPDATE_PROPERTY: | |
170 | if (is_status) { | |
171 | prev_state = old_status_state != 0; | |
172 | new_state = status_state != 0; | |
173 | } | |
174 | break; | |
175 | } | |
176 | ||
177 | if (prev_state == new_state) | |
178 | return OF_RECONFIG_NO_CHANGE; | |
179 | ||
180 | return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE; | |
181 | } | |
182 | EXPORT_SYMBOL_GPL(of_reconfig_get_state_change); | |
183 | ||
6afc0dc3 | 184 | int of_property_notify(int action, struct device_node *np, |
259092a3 | 185 | struct property *prop, struct property *oldprop) |
6afc0dc3 | 186 | { |
f5242e5a | 187 | struct of_reconfig_data pr; |
6afc0dc3 GL |
188 | |
189 | /* only call notifiers if the node is attached */ | |
190 | if (!of_node_is_attached(np)) | |
191 | return 0; | |
192 | ||
193 | pr.dn = np; | |
194 | pr.prop = prop; | |
259092a3 | 195 | pr.old_prop = oldprop; |
6afc0dc3 GL |
196 | return of_reconfig_notify(action, &pr); |
197 | } | |
198 | ||
24996951 | 199 | static void __of_attach_node(struct device_node *np) |
d8c50088 | 200 | { |
a25095d4 GL |
201 | const __be32 *phandle; |
202 | int sz; | |
fab610be RH |
203 | unsigned long flags; |
204 | ||
205 | raw_spin_lock_irqsave(&devtree_lock, flags); | |
a25095d4 | 206 | |
f9627881 FR |
207 | if (!of_node_check_flag(np, OF_OVERLAY)) { |
208 | np->name = __of_get_property(np, "name", NULL); | |
f9627881 FR |
209 | if (!np->name) |
210 | np->name = "<NULL>"; | |
f9627881 FR |
211 | |
212 | phandle = __of_get_property(np, "phandle", &sz); | |
213 | if (!phandle) | |
214 | phandle = __of_get_property(np, "linux,phandle", &sz); | |
215 | if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) | |
216 | phandle = __of_get_property(np, "ibm,phandle", &sz); | |
217 | if (phandle && (sz >= 4)) | |
218 | np->phandle = be32_to_cpup(phandle); | |
219 | else | |
220 | np->phandle = 0; | |
221 | } | |
a25095d4 | 222 | |
6162dbe4 | 223 | np->child = NULL; |
d8c50088 | 224 | np->sibling = np->parent->child; |
d8c50088 PA |
225 | np->parent->child = np; |
226 | of_node_clear_flag(np, OF_DETACHED); | |
1a50d940 | 227 | np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE; |
fab610be RH |
228 | |
229 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | |
230 | ||
231 | __of_attach_node_sysfs(np); | |
d8c50088 PA |
232 | } |
233 | ||
6afc0dc3 GL |
234 | /** |
235 | * of_attach_node() - Plug a device node into the tree and global list. | |
3cb025d9 | 236 | * @np: Pointer to the caller's Device Node |
6afc0dc3 GL |
237 | */ |
238 | int of_attach_node(struct device_node *np) | |
239 | { | |
f5242e5a | 240 | struct of_reconfig_data rd; |
6afc0dc3 | 241 | |
f5242e5a GL |
242 | memset(&rd, 0, sizeof(rd)); |
243 | rd.dn = np; | |
244 | ||
8a2b22a2 | 245 | mutex_lock(&of_mutex); |
d8c50088 | 246 | __of_attach_node(np); |
8a2b22a2 | 247 | mutex_unlock(&of_mutex); |
259092a3 | 248 | |
f5242e5a | 249 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd); |
259092a3 | 250 | |
6afc0dc3 GL |
251 | return 0; |
252 | } | |
253 | ||
d8c50088 | 254 | void __of_detach_node(struct device_node *np) |
6afc0dc3 GL |
255 | { |
256 | struct device_node *parent; | |
fab610be | 257 | unsigned long flags; |
6afc0dc3 | 258 | |
fab610be | 259 | raw_spin_lock_irqsave(&devtree_lock, flags); |
6afc0dc3 GL |
260 | |
261 | parent = np->parent; | |
fab610be RH |
262 | if (WARN_ON(of_node_check_flag(np, OF_DETACHED) || !parent)) { |
263 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | |
d8c50088 | 264 | return; |
fab610be | 265 | } |
6afc0dc3 | 266 | |
6afc0dc3 GL |
267 | if (parent->child == np) |
268 | parent->child = np->sibling; | |
269 | else { | |
270 | struct device_node *prevsib; | |
271 | for (prevsib = np->parent->child; | |
272 | prevsib->sibling != np; | |
273 | prevsib = prevsib->sibling) | |
274 | ; | |
275 | prevsib->sibling = np->sibling; | |
276 | } | |
277 | ||
278 | of_node_set_flag(np, OF_DETACHED); | |
5801169a FR |
279 | |
280 | /* race with of_find_node_by_phandle() prevented by devtree_lock */ | |
90dc0d1c | 281 | __of_phandle_cache_inv_entry(np->phandle); |
fab610be RH |
282 | |
283 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | |
284 | ||
285 | __of_detach_node_sysfs(np); | |
d8c50088 PA |
286 | } |
287 | ||
288 | /** | |
289 | * of_detach_node() - "Unplug" a node from the device tree. | |
3cb025d9 | 290 | * @np: Pointer to the caller's Device Node |
d8c50088 PA |
291 | */ |
292 | int of_detach_node(struct device_node *np) | |
293 | { | |
f5242e5a | 294 | struct of_reconfig_data rd; |
d8c50088 | 295 | |
f5242e5a GL |
296 | memset(&rd, 0, sizeof(rd)); |
297 | rd.dn = np; | |
298 | ||
8a2b22a2 | 299 | mutex_lock(&of_mutex); |
d8c50088 | 300 | __of_detach_node(np); |
8a2b22a2 | 301 | mutex_unlock(&of_mutex); |
259092a3 | 302 | |
f5242e5a | 303 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd); |
259092a3 | 304 | |
58fb82cc | 305 | return 0; |
6afc0dc3 | 306 | } |
bb91f923 | 307 | EXPORT_SYMBOL_GPL(of_detach_node); |
6afc0dc3 | 308 | |
070ea018 LW |
309 | static void property_list_free(struct property *prop_list) |
310 | { | |
311 | struct property *prop, *next; | |
312 | ||
313 | for (prop = prop_list; prop != NULL; prop = next) { | |
314 | next = prop->next; | |
315 | kfree(prop->name); | |
316 | kfree(prop->value); | |
317 | kfree(prop); | |
318 | } | |
319 | } | |
320 | ||
6afc0dc3 GL |
321 | /** |
322 | * of_node_release() - release a dynamically allocated node | |
3cb025d9 | 323 | * @kobj: kernel object of the node to be released |
6afc0dc3 GL |
324 | * |
325 | * In of_node_put() this function is passed to kref_put() as the destructor. | |
326 | */ | |
327 | void of_node_release(struct kobject *kobj) | |
328 | { | |
329 | struct device_node *node = kobj_to_device_node(kobj); | |
6afc0dc3 | 330 | |
23522dd7 FR |
331 | /* |
332 | * can not use '"%pOF", node' in pr_err() calls from this function | |
333 | * because an of_node_get(node) when refcount is already zero | |
334 | * will result in an error and a stack dump | |
335 | */ | |
336 | ||
6afc0dc3 GL |
337 | /* We should never be releasing nodes that haven't been detached. */ |
338 | if (!of_node_check_flag(node, OF_DETACHED)) { | |
23522dd7 FR |
339 | |
340 | pr_err("ERROR: %s() detected bad of_node_put() on %pOF/%s\n", | |
341 | __func__, node->parent, node->full_name); | |
74df14cd FR |
342 | |
343 | /* | |
344 | * of unittests will test this path. Do not print the stack | |
345 | * trace when the error is caused by unittest so that we do | |
346 | * not display what a normal developer might reasonably | |
347 | * consider a real bug. | |
348 | */ | |
349 | if (!IS_ENABLED(CONFIG_OF_UNITTEST) || | |
350 | strcmp(node->parent->full_name, "testcase-data")) { | |
351 | dump_stack(); | |
b4858dc6 | 352 | pr_err("ERROR: next of_node_put() on this node will result in a kobject warning 'refcount_t: underflow; use-after-free.'\n"); |
74df14cd FR |
353 | } |
354 | ||
6afc0dc3 GL |
355 | return; |
356 | } | |
6afc0dc3 GL |
357 | if (!of_node_check_flag(node, OF_DYNAMIC)) |
358 | return; | |
359 | ||
144552c7 FR |
360 | if (of_node_check_flag(node, OF_OVERLAY)) { |
361 | ||
362 | if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) { | |
363 | /* premature refcount of zero, do not free memory */ | |
364 | pr_err("ERROR: memory leak before free overlay changeset, %pOF\n", | |
365 | node); | |
366 | return; | |
367 | } | |
368 | ||
369 | /* | |
370 | * If node->properties non-empty then properties were added | |
371 | * to this node either by different overlay that has not | |
372 | * yet been removed, or by a non-overlay mechanism. | |
373 | */ | |
374 | if (node->properties) | |
375 | pr_err("ERROR: %s(), unexpected properties in %pOF\n", | |
376 | __func__, node); | |
377 | } | |
378 | ||
ec0b7e24 FR |
379 | if (node->child) |
380 | pr_err("ERROR: %s() unexpected children for %pOF/%s\n", | |
381 | __func__, node->parent, node->full_name); | |
382 | ||
070ea018 LW |
383 | property_list_free(node->properties); |
384 | property_list_free(node->deadprops); | |
7b337cb3 | 385 | fwnode_links_purge(of_fwnode_handle(node)); |
6afc0dc3 | 386 | |
6afc0dc3 GL |
387 | kfree(node->full_name); |
388 | kfree(node->data); | |
389 | kfree(node); | |
390 | } | |
69843396 PA |
391 | |
392 | /** | |
393 | * __of_prop_dup - Copy a property dynamically. | |
394 | * @prop: Property to copy | |
395 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | |
396 | * | |
397 | * Copy a property by dynamically allocating the memory of both the | |
27b3383a | 398 | * property structure and the property name & contents. The property's |
69843396 PA |
399 | * flags have the OF_DYNAMIC bit set so that we can differentiate between |
400 | * dynamically allocated properties and not. | |
8c8239c2 RH |
401 | * |
402 | * Return: The newly allocated property or NULL on out of memory error. | |
69843396 PA |
403 | */ |
404 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) | |
405 | { | |
406 | struct property *new; | |
407 | ||
408 | new = kzalloc(sizeof(*new), allocflags); | |
409 | if (!new) | |
410 | return NULL; | |
411 | ||
412 | /* | |
413 | * NOTE: There is no check for zero length value. | |
b6ae5dc5 | 414 | * In case of a boolean property, this will allocate a value |
69843396 PA |
415 | * of zero bytes. We do this to work around the use |
416 | * of of_get_property() calls on boolean values. | |
417 | */ | |
418 | new->name = kstrdup(prop->name, allocflags); | |
419 | new->value = kmemdup(prop->value, prop->length, allocflags); | |
420 | new->length = prop->length; | |
421 | if (!new->name || !new->value) | |
422 | goto err_free; | |
423 | ||
424 | /* mark the property as dynamic */ | |
425 | of_property_set_flag(new, OF_DYNAMIC); | |
426 | ||
427 | return new; | |
428 | ||
429 | err_free: | |
430 | kfree(new->name); | |
431 | kfree(new->value); | |
432 | kfree(new); | |
433 | return NULL; | |
434 | } | |
435 | ||
436 | /** | |
e5179581 | 437 | * __of_node_dup() - Duplicate or create an empty device node dynamically. |
b89dae18 FR |
438 | * @np: if not NULL, contains properties to be duplicated in new node |
439 | * @full_name: string value to be duplicated into new node's full_name field | |
69843396 | 440 | * |
b89dae18 FR |
441 | * Create a device tree node, optionally duplicating the properties of |
442 | * another node. The node data are dynamically allocated and all the node | |
443 | * flags have the OF_DYNAMIC & OF_DETACHED bits set. | |
444 | * | |
d9194e00 FR |
445 | * Return: The newly allocated node or NULL on out of memory error. Use |
446 | * of_node_put() on it when done to free the memory allocated for it. | |
69843396 | 447 | */ |
b89dae18 FR |
448 | struct device_node *__of_node_dup(const struct device_node *np, |
449 | const char *full_name) | |
69843396 PA |
450 | { |
451 | struct device_node *node; | |
452 | ||
ef8bbd73 | 453 | node = kzalloc(sizeof(*node), GFP_KERNEL); |
69843396 PA |
454 | if (!node) |
455 | return NULL; | |
b89dae18 | 456 | node->full_name = kstrdup(full_name, GFP_KERNEL); |
e5179581 GL |
457 | if (!node->full_name) { |
458 | kfree(node); | |
459 | return NULL; | |
460 | } | |
69843396 | 461 | |
ef8bbd73 GL |
462 | of_node_set_flag(node, OF_DYNAMIC); |
463 | of_node_set_flag(node, OF_DETACHED); | |
69843396 PA |
464 | of_node_init(node); |
465 | ||
e5179581 GL |
466 | /* Iterate over and duplicate all properties */ |
467 | if (np) { | |
468 | struct property *pp, *new_pp; | |
469 | for_each_property_of_node(np, pp) { | |
470 | new_pp = __of_prop_dup(pp, GFP_KERNEL); | |
471 | if (!new_pp) | |
472 | goto err_prop; | |
473 | if (__of_add_property(node, new_pp)) { | |
474 | kfree(new_pp->name); | |
475 | kfree(new_pp->value); | |
476 | kfree(new_pp); | |
477 | goto err_prop; | |
478 | } | |
479 | } | |
480 | } | |
69843396 PA |
481 | return node; |
482 | ||
e5179581 GL |
483 | err_prop: |
484 | of_node_put(node); /* Frees the node and properties */ | |
69843396 PA |
485 | return NULL; |
486 | } | |
201c910b | 487 | |
b544fc2b LH |
488 | /** |
489 | * of_changeset_create_node - Dynamically create a device node and attach to | |
490 | * a given changeset. | |
491 | * | |
492 | * @ocs: Pointer to changeset | |
493 | * @parent: Pointer to parent device node | |
494 | * @full_name: Node full name | |
495 | * | |
496 | * Return: Pointer to the created device node or NULL in case of an error. | |
497 | */ | |
498 | struct device_node *of_changeset_create_node(struct of_changeset *ocs, | |
499 | struct device_node *parent, | |
500 | const char *full_name) | |
501 | { | |
502 | struct device_node *np; | |
503 | int ret; | |
504 | ||
505 | np = __of_node_dup(NULL, full_name); | |
506 | if (!np) | |
507 | return NULL; | |
508 | np->parent = parent; | |
509 | ||
510 | ret = of_changeset_attach_node(ocs, np); | |
511 | if (ret) { | |
512 | of_node_put(np); | |
513 | return NULL; | |
514 | } | |
515 | ||
516 | return np; | |
517 | } | |
518 | EXPORT_SYMBOL(of_changeset_create_node); | |
519 | ||
201c910b PA |
520 | static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) |
521 | { | |
144552c7 FR |
522 | if (ce->action == OF_RECONFIG_ATTACH_NODE && |
523 | of_node_check_flag(ce->np, OF_OVERLAY)) { | |
524 | if (kref_read(&ce->np->kobj.kref) > 1) { | |
525 | 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", | |
526 | kref_read(&ce->np->kobj.kref), ce->np); | |
527 | } else { | |
528 | of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET); | |
529 | } | |
530 | } | |
531 | ||
201c910b PA |
532 | of_node_put(ce->np); |
533 | list_del(&ce->node); | |
534 | kfree(ce); | |
535 | } | |
536 | ||
201c910b PA |
537 | static void __of_changeset_entry_invert(struct of_changeset_entry *ce, |
538 | struct of_changeset_entry *rce) | |
539 | { | |
540 | memcpy(rce, ce, sizeof(*rce)); | |
541 | ||
542 | switch (ce->action) { | |
543 | case OF_RECONFIG_ATTACH_NODE: | |
544 | rce->action = OF_RECONFIG_DETACH_NODE; | |
545 | break; | |
546 | case OF_RECONFIG_DETACH_NODE: | |
547 | rce->action = OF_RECONFIG_ATTACH_NODE; | |
548 | break; | |
549 | case OF_RECONFIG_ADD_PROPERTY: | |
550 | rce->action = OF_RECONFIG_REMOVE_PROPERTY; | |
551 | break; | |
552 | case OF_RECONFIG_REMOVE_PROPERTY: | |
553 | rce->action = OF_RECONFIG_ADD_PROPERTY; | |
554 | break; | |
555 | case OF_RECONFIG_UPDATE_PROPERTY: | |
556 | rce->old_prop = ce->prop; | |
557 | rce->prop = ce->old_prop; | |
b9c43856 PA |
558 | /* update was used but original property did not exist */ |
559 | if (!rce->prop) { | |
560 | rce->action = OF_RECONFIG_REMOVE_PROPERTY; | |
561 | rce->prop = ce->prop; | |
562 | } | |
201c910b PA |
563 | break; |
564 | } | |
565 | } | |
566 | ||
24789c5c FR |
567 | static int __of_changeset_entry_notify(struct of_changeset_entry *ce, |
568 | bool revert) | |
201c910b | 569 | { |
f5242e5a | 570 | struct of_reconfig_data rd; |
201c910b | 571 | struct of_changeset_entry ce_inverted; |
24789c5c | 572 | int ret = 0; |
201c910b PA |
573 | |
574 | if (revert) { | |
575 | __of_changeset_entry_invert(ce, &ce_inverted); | |
576 | ce = &ce_inverted; | |
577 | } | |
578 | ||
579 | switch (ce->action) { | |
580 | case OF_RECONFIG_ATTACH_NODE: | |
581 | case OF_RECONFIG_DETACH_NODE: | |
f5242e5a GL |
582 | memset(&rd, 0, sizeof(rd)); |
583 | rd.dn = ce->np; | |
584 | ret = of_reconfig_notify(ce->action, &rd); | |
201c910b PA |
585 | break; |
586 | case OF_RECONFIG_ADD_PROPERTY: | |
587 | case OF_RECONFIG_REMOVE_PROPERTY: | |
588 | case OF_RECONFIG_UPDATE_PROPERTY: | |
589 | ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop); | |
590 | break; | |
591 | default: | |
606ad42a | 592 | pr_err("invalid devicetree changeset action: %i\n", |
201c910b | 593 | (int)ce->action); |
24789c5c | 594 | ret = -EINVAL; |
201c910b PA |
595 | } |
596 | ||
597 | if (ret) | |
0d638a07 | 598 | pr_err("changeset notifier error @%pOF\n", ce->np); |
24789c5c | 599 | return ret; |
201c910b PA |
600 | } |
601 | ||
602 | static int __of_changeset_entry_apply(struct of_changeset_entry *ce) | |
603 | { | |
201c910b PA |
604 | int ret = 0; |
605 | ||
27a02f26 | 606 | of_changeset_action_debug("apply: ", ce->action, ce->np, ce->prop); |
201c910b | 607 | |
201c910b PA |
608 | switch (ce->action) { |
609 | case OF_RECONFIG_ATTACH_NODE: | |
610 | __of_attach_node(ce->np); | |
611 | break; | |
612 | case OF_RECONFIG_DETACH_NODE: | |
613 | __of_detach_node(ce->np); | |
614 | break; | |
615 | case OF_RECONFIG_ADD_PROPERTY: | |
201c910b | 616 | ret = __of_add_property(ce->np, ce->prop); |
201c910b PA |
617 | break; |
618 | case OF_RECONFIG_REMOVE_PROPERTY: | |
619 | ret = __of_remove_property(ce->np, ce->prop); | |
201c910b PA |
620 | break; |
621 | ||
622 | case OF_RECONFIG_UPDATE_PROPERTY: | |
420f0de9 | 623 | ret = __of_update_property(ce->np, ce->prop, &ce->old_prop); |
201c910b PA |
624 | break; |
625 | default: | |
626 | ret = -EINVAL; | |
627 | } | |
201c910b | 628 | |
914d9d83 | 629 | if (ret) { |
27a02f26 | 630 | of_changeset_action_err("apply failed: ", ce->action, ce->np, ce->prop); |
201c910b | 631 | return ret; |
914d9d83 | 632 | } |
201c910b | 633 | |
201c910b PA |
634 | return 0; |
635 | } | |
636 | ||
637 | static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce) | |
638 | { | |
639 | struct of_changeset_entry ce_inverted; | |
640 | ||
641 | __of_changeset_entry_invert(ce, &ce_inverted); | |
642 | return __of_changeset_entry_apply(&ce_inverted); | |
643 | } | |
644 | ||
645 | /** | |
646 | * of_changeset_init - Initialize a changeset for use | |
647 | * | |
648 | * @ocs: changeset pointer | |
649 | * | |
650 | * Initialize a changeset structure | |
651 | */ | |
652 | void of_changeset_init(struct of_changeset *ocs) | |
653 | { | |
654 | memset(ocs, 0, sizeof(*ocs)); | |
655 | INIT_LIST_HEAD(&ocs->entries); | |
656 | } | |
18322377 | 657 | EXPORT_SYMBOL_GPL(of_changeset_init); |
201c910b PA |
658 | |
659 | /** | |
660 | * of_changeset_destroy - Destroy a changeset | |
661 | * | |
662 | * @ocs: changeset pointer | |
663 | * | |
664 | * Destroys a changeset. Note that if a changeset is applied, | |
665 | * its changes to the tree cannot be reverted. | |
666 | */ | |
667 | void of_changeset_destroy(struct of_changeset *ocs) | |
668 | { | |
669 | struct of_changeset_entry *ce, *cen; | |
670 | ||
801c8b8e HC |
671 | /* |
672 | * When a device is deleted, the device links to/from it are also queued | |
673 | * for deletion. Until these device links are freed, the devices | |
674 | * themselves aren't freed. If the device being deleted is due to an | |
675 | * overlay change, this device might be holding a reference to a device | |
676 | * node that will be freed. So, wait until all already pending device | |
677 | * links are deleted before freeing a device node. This ensures we don't | |
678 | * free any device node that has a non-zero reference count. | |
679 | */ | |
680 | device_link_wait_removal(); | |
681 | ||
201c910b PA |
682 | list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node) |
683 | __of_changeset_entry_destroy(ce); | |
684 | } | |
18322377 | 685 | EXPORT_SYMBOL_GPL(of_changeset_destroy); |
201c910b | 686 | |
24789c5c FR |
687 | /* |
688 | * Apply the changeset entries in @ocs. | |
689 | * If apply fails, an attempt is made to revert the entries that were | |
690 | * successfully applied. | |
691 | * | |
692 | * If multiple revert errors occur then only the final revert error is reported. | |
693 | * | |
694 | * Returns 0 on success, a negative error value in case of an error. | |
695 | * If a revert error occurs, it is returned in *ret_revert. | |
696 | */ | |
697 | int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert) | |
201c910b PA |
698 | { |
699 | struct of_changeset_entry *ce; | |
24789c5c | 700 | int ret, ret_tmp; |
201c910b | 701 | |
606ad42a | 702 | pr_debug("changeset: applying...\n"); |
201c910b PA |
703 | list_for_each_entry(ce, &ocs->entries, node) { |
704 | ret = __of_changeset_entry_apply(ce); | |
705 | if (ret) { | |
606ad42a | 706 | pr_err("Error applying changeset (%d)\n", ret); |
24789c5c FR |
707 | list_for_each_entry_continue_reverse(ce, &ocs->entries, |
708 | node) { | |
709 | ret_tmp = __of_changeset_entry_revert(ce); | |
710 | if (ret_tmp) | |
711 | *ret_revert = ret_tmp; | |
712 | } | |
201c910b PA |
713 | return ret; |
714 | } | |
715 | } | |
24789c5c FR |
716 | |
717 | return 0; | |
718 | } | |
719 | ||
720 | /* | |
721 | * Returns 0 on success, a negative error value in case of an error. | |
722 | * | |
e9d92e40 | 723 | * If multiple changeset entry notification errors occur then only the |
24789c5c FR |
724 | * final notification error is reported. |
725 | */ | |
726 | int __of_changeset_apply_notify(struct of_changeset *ocs) | |
727 | { | |
728 | struct of_changeset_entry *ce; | |
729 | int ret = 0, ret_tmp; | |
730 | ||
731 | pr_debug("changeset: emitting notifiers.\n"); | |
201c910b PA |
732 | |
733 | /* drop the global lock while emitting notifiers */ | |
734 | mutex_unlock(&of_mutex); | |
24789c5c FR |
735 | list_for_each_entry(ce, &ocs->entries, node) { |
736 | ret_tmp = __of_changeset_entry_notify(ce, 0); | |
737 | if (ret_tmp) | |
738 | ret = ret_tmp; | |
739 | } | |
201c910b | 740 | mutex_lock(&of_mutex); |
606ad42a | 741 | pr_debug("changeset: notifiers sent.\n"); |
201c910b | 742 | |
24789c5c FR |
743 | return ret; |
744 | } | |
745 | ||
746 | /* | |
747 | * Returns 0 on success, a negative error value in case of an error. | |
748 | * | |
749 | * If a changeset entry apply fails, an attempt is made to revert any | |
750 | * previous entries in the changeset. If any of the reverts fails, | |
751 | * that failure is not reported. Thus the state of the device tree | |
752 | * is unknown if an apply error occurs. | |
753 | */ | |
754 | static int __of_changeset_apply(struct of_changeset *ocs) | |
755 | { | |
756 | int ret, ret_revert = 0; | |
757 | ||
758 | ret = __of_changeset_apply_entries(ocs, &ret_revert); | |
759 | if (!ret) | |
760 | ret = __of_changeset_apply_notify(ocs); | |
761 | ||
762 | return ret; | |
201c910b PA |
763 | } |
764 | ||
765 | /** | |
18322377 | 766 | * of_changeset_apply - Applies a changeset |
201c910b PA |
767 | * |
768 | * @ocs: changeset pointer | |
769 | * | |
18322377 GS |
770 | * Applies a changeset to the live tree. |
771 | * Any side-effects of live tree state changes are applied here on | |
772 | * success, like creation/destruction of devices and side-effects | |
773 | * like creation of sysfs properties and directories. | |
8c8239c2 RH |
774 | * |
775 | * Return: 0 on success, a negative error value in case of an error. | |
18322377 | 776 | * On error the partially applied effects are reverted. |
201c910b | 777 | */ |
18322377 GS |
778 | int of_changeset_apply(struct of_changeset *ocs) |
779 | { | |
780 | int ret; | |
781 | ||
782 | mutex_lock(&of_mutex); | |
783 | ret = __of_changeset_apply(ocs); | |
784 | mutex_unlock(&of_mutex); | |
785 | ||
786 | return ret; | |
787 | } | |
788 | EXPORT_SYMBOL_GPL(of_changeset_apply); | |
789 | ||
24789c5c FR |
790 | /* |
791 | * Revert the changeset entries in @ocs. | |
792 | * If revert fails, an attempt is made to re-apply the entries that were | |
793 | * successfully removed. | |
794 | * | |
795 | * If multiple re-apply errors occur then only the final apply error is | |
796 | * reported. | |
797 | * | |
798 | * Returns 0 on success, a negative error value in case of an error. | |
799 | * If an apply error occurs, it is returned in *ret_apply. | |
800 | */ | |
801 | int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply) | |
201c910b PA |
802 | { |
803 | struct of_changeset_entry *ce; | |
24789c5c | 804 | int ret, ret_tmp; |
201c910b | 805 | |
606ad42a | 806 | pr_debug("changeset: reverting...\n"); |
201c910b PA |
807 | list_for_each_entry_reverse(ce, &ocs->entries, node) { |
808 | ret = __of_changeset_entry_revert(ce); | |
809 | if (ret) { | |
606ad42a | 810 | pr_err("Error reverting changeset (%d)\n", ret); |
24789c5c FR |
811 | list_for_each_entry_continue(ce, &ocs->entries, node) { |
812 | ret_tmp = __of_changeset_entry_apply(ce); | |
813 | if (ret_tmp) | |
814 | *ret_apply = ret_tmp; | |
815 | } | |
201c910b PA |
816 | return ret; |
817 | } | |
818 | } | |
24789c5c FR |
819 | |
820 | return 0; | |
821 | } | |
822 | ||
823 | /* | |
e9d92e40 | 824 | * If multiple changeset entry notification errors occur then only the |
24789c5c FR |
825 | * final notification error is reported. |
826 | */ | |
827 | int __of_changeset_revert_notify(struct of_changeset *ocs) | |
828 | { | |
829 | struct of_changeset_entry *ce; | |
830 | int ret = 0, ret_tmp; | |
831 | ||
832 | pr_debug("changeset: emitting notifiers.\n"); | |
201c910b PA |
833 | |
834 | /* drop the global lock while emitting notifiers */ | |
835 | mutex_unlock(&of_mutex); | |
24789c5c FR |
836 | list_for_each_entry_reverse(ce, &ocs->entries, node) { |
837 | ret_tmp = __of_changeset_entry_notify(ce, 1); | |
838 | if (ret_tmp) | |
839 | ret = ret_tmp; | |
840 | } | |
201c910b | 841 | mutex_lock(&of_mutex); |
606ad42a | 842 | pr_debug("changeset: notifiers sent.\n"); |
201c910b | 843 | |
24789c5c FR |
844 | return ret; |
845 | } | |
846 | ||
847 | static int __of_changeset_revert(struct of_changeset *ocs) | |
848 | { | |
849 | int ret, ret_reply; | |
850 | ||
851 | ret_reply = 0; | |
852 | ret = __of_changeset_revert_entries(ocs, &ret_reply); | |
853 | ||
854 | if (!ret) | |
855 | ret = __of_changeset_revert_notify(ocs); | |
856 | ||
857 | return ret; | |
201c910b PA |
858 | } |
859 | ||
18322377 GS |
860 | /** |
861 | * of_changeset_revert - Reverts an applied changeset | |
862 | * | |
863 | * @ocs: changeset pointer | |
864 | * | |
865 | * Reverts a changeset returning the state of the tree to what it | |
866 | * was before the application. | |
867 | * Any side-effects like creation/destruction of devices and | |
868 | * removal of sysfs properties and directories are applied. | |
8c8239c2 RH |
869 | * |
870 | * Return: 0 on success, a negative error value in case of an error. | |
18322377 GS |
871 | */ |
872 | int of_changeset_revert(struct of_changeset *ocs) | |
873 | { | |
874 | int ret; | |
875 | ||
876 | mutex_lock(&of_mutex); | |
877 | ret = __of_changeset_revert(ocs); | |
878 | mutex_unlock(&of_mutex); | |
879 | ||
880 | return ret; | |
881 | } | |
882 | EXPORT_SYMBOL_GPL(of_changeset_revert); | |
883 | ||
201c910b | 884 | /** |
0290c4ca | 885 | * of_changeset_action - Add an action to the tail of the changeset list |
201c910b PA |
886 | * |
887 | * @ocs: changeset pointer | |
888 | * @action: action to perform | |
889 | * @np: Pointer to device node | |
890 | * @prop: Pointer to property | |
891 | * | |
892 | * On action being one of: | |
893 | * + OF_RECONFIG_ATTACH_NODE | |
894 | * + OF_RECONFIG_DETACH_NODE, | |
895 | * + OF_RECONFIG_ADD_PROPERTY | |
896 | * + OF_RECONFIG_REMOVE_PROPERTY, | |
897 | * + OF_RECONFIG_UPDATE_PROPERTY | |
8c8239c2 RH |
898 | * |
899 | * Return: 0 on success, a negative error value in case of an error. | |
201c910b PA |
900 | */ |
901 | int of_changeset_action(struct of_changeset *ocs, unsigned long action, | |
902 | struct device_node *np, struct property *prop) | |
903 | { | |
904 | struct of_changeset_entry *ce; | |
905 | ||
55e95bfc DC |
906 | if (WARN_ON(action >= ARRAY_SIZE(action_names))) |
907 | return -EINVAL; | |
908 | ||
201c910b | 909 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); |
606ad42a | 910 | if (!ce) |
201c910b | 911 | return -ENOMEM; |
606ad42a | 912 | |
201c910b PA |
913 | /* get a reference to the node */ |
914 | ce->action = action; | |
915 | ce->np = of_node_get(np); | |
916 | ce->prop = prop; | |
917 | ||
201c910b PA |
918 | /* add it to the list */ |
919 | list_add_tail(&ce->node, &ocs->entries); | |
920 | return 0; | |
921 | } | |
18322377 | 922 | EXPORT_SYMBOL_GPL(of_changeset_action); |
b544fc2b LH |
923 | |
924 | static int of_changeset_add_prop_helper(struct of_changeset *ocs, | |
925 | struct device_node *np, | |
926 | const struct property *pp) | |
927 | { | |
928 | struct property *new_pp; | |
929 | int ret; | |
930 | ||
931 | new_pp = __of_prop_dup(pp, GFP_KERNEL); | |
932 | if (!new_pp) | |
933 | return -ENOMEM; | |
934 | ||
935 | ret = of_changeset_add_property(ocs, np, new_pp); | |
936 | if (ret) { | |
937 | kfree(new_pp->name); | |
938 | kfree(new_pp->value); | |
939 | kfree(new_pp); | |
940 | } | |
941 | ||
942 | return ret; | |
943 | } | |
944 | ||
945 | /** | |
946 | * of_changeset_add_prop_string - Add a string property to a changeset | |
947 | * | |
948 | * @ocs: changeset pointer | |
949 | * @np: device node pointer | |
950 | * @prop_name: name of the property to be added | |
951 | * @str: pointer to null terminated string | |
952 | * | |
953 | * Create a string property and add it to a changeset. | |
954 | * | |
955 | * Return: 0 on success, a negative error value in case of an error. | |
956 | */ | |
957 | int of_changeset_add_prop_string(struct of_changeset *ocs, | |
958 | struct device_node *np, | |
959 | const char *prop_name, const char *str) | |
960 | { | |
961 | struct property prop; | |
962 | ||
963 | prop.name = (char *)prop_name; | |
964 | prop.length = strlen(str) + 1; | |
965 | prop.value = (void *)str; | |
966 | ||
967 | return of_changeset_add_prop_helper(ocs, np, &prop); | |
968 | } | |
969 | EXPORT_SYMBOL_GPL(of_changeset_add_prop_string); | |
970 | ||
971 | /** | |
972 | * of_changeset_add_prop_string_array - Add a string list property to | |
973 | * a changeset | |
974 | * | |
975 | * @ocs: changeset pointer | |
976 | * @np: device node pointer | |
977 | * @prop_name: name of the property to be added | |
978 | * @str_array: pointer to an array of null terminated strings | |
979 | * @sz: number of string array elements | |
980 | * | |
981 | * Create a string list property and add it to a changeset. | |
982 | * | |
983 | * Return: 0 on success, a negative error value in case of an error. | |
984 | */ | |
985 | int of_changeset_add_prop_string_array(struct of_changeset *ocs, | |
986 | struct device_node *np, | |
987 | const char *prop_name, | |
988 | const char **str_array, size_t sz) | |
989 | { | |
990 | struct property prop; | |
991 | int i, ret; | |
992 | char *vp; | |
993 | ||
994 | prop.name = (char *)prop_name; | |
995 | ||
996 | prop.length = 0; | |
997 | for (i = 0; i < sz; i++) | |
998 | prop.length += strlen(str_array[i]) + 1; | |
999 | ||
1000 | prop.value = kmalloc(prop.length, GFP_KERNEL); | |
1001 | if (!prop.value) | |
1002 | return -ENOMEM; | |
1003 | ||
1004 | vp = prop.value; | |
1005 | for (i = 0; i < sz; i++) { | |
1006 | vp += snprintf(vp, (char *)prop.value + prop.length - vp, "%s", | |
1007 | str_array[i]) + 1; | |
1008 | } | |
1009 | ret = of_changeset_add_prop_helper(ocs, np, &prop); | |
1010 | kfree(prop.value); | |
1011 | ||
1012 | return ret; | |
1013 | } | |
1014 | EXPORT_SYMBOL_GPL(of_changeset_add_prop_string_array); | |
1015 | ||
1016 | /** | |
1017 | * of_changeset_add_prop_u32_array - Add a property of 32 bit integers | |
1018 | * property to a changeset | |
1019 | * | |
1020 | * @ocs: changeset pointer | |
1021 | * @np: device node pointer | |
1022 | * @prop_name: name of the property to be added | |
1023 | * @array: pointer to an array of 32 bit integers | |
1024 | * @sz: number of array elements | |
1025 | * | |
1026 | * Create a property of 32 bit integers and add it to a changeset. | |
1027 | * | |
1028 | * Return: 0 on success, a negative error value in case of an error. | |
1029 | */ | |
1030 | int of_changeset_add_prop_u32_array(struct of_changeset *ocs, | |
1031 | struct device_node *np, | |
1032 | const char *prop_name, | |
1033 | const u32 *array, size_t sz) | |
1034 | { | |
1035 | struct property prop; | |
1036 | __be32 *val; | |
1037 | int i, ret; | |
1038 | ||
1039 | val = kcalloc(sz, sizeof(__be32), GFP_KERNEL); | |
1040 | if (!val) | |
1041 | return -ENOMEM; | |
1042 | ||
1043 | for (i = 0; i < sz; i++) | |
1044 | val[i] = cpu_to_be32(array[i]); | |
1045 | prop.name = (char *)prop_name; | |
1046 | prop.length = sizeof(u32) * sz; | |
1047 | prop.value = (void *)val; | |
1048 | ||
1049 | ret = of_changeset_add_prop_helper(ocs, np, &prop); | |
1050 | kfree(val); | |
1051 | ||
1052 | return ret; | |
1053 | } | |
1054 | EXPORT_SYMBOL_GPL(of_changeset_add_prop_u32_array); |