1 | // SPDX-License-Identifier: GPL-2.0 |
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 | |
10 | #define pr_fmt(fmt) "OF: " fmt |
11 | |
12 | #include <linux/device.h> |
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 | |
21 | static struct device_node *kobj_to_device_node(struct kobject *kobj) |
22 | { |
23 | return container_of(kobj, struct device_node, kobj); |
24 | } |
25 | |
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 | * |
31 | * Return: The node with refcount incremented. |
32 | */ |
33 | struct device_node *of_node_get(struct device_node *node) |
34 | { |
35 | if (node) |
36 | kobject_get(kobj: &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(kobj: &node->kobj); |
50 | } |
51 | EXPORT_SYMBOL(of_node_put); |
52 | |
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(nh: &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(nh: &of_reconfig_chain, nb); |
64 | } |
65 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); |
66 | |
67 | static const char *action_names[] = { |
68 | [0] = "INVALID" , |
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 | }; |
75 | |
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 | |
84 | int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) |
85 | { |
86 | int rc; |
87 | struct of_reconfig_data *pr = p; |
88 | |
89 | of_changeset_action_debug("notify: " , action, pr->dn, pr->prop); |
90 | |
91 | rc = blocking_notifier_call_chain(nh: &of_reconfig_chain, val: action, v: p); |
92 | return notifier_to_errno(ret: rc); |
93 | } |
94 | |
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. |
101 | * |
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. |
105 | */ |
106 | int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) |
107 | { |
108 | struct property *prop, *old_prop = NULL; |
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 */ |
112 | switch (action) { |
113 | case OF_RECONFIG_ATTACH_NODE: |
114 | case OF_RECONFIG_DETACH_NODE: |
115 | prop = of_find_property(np: pr->dn, name: "status" , NULL); |
116 | break; |
117 | case OF_RECONFIG_ADD_PROPERTY: |
118 | case OF_RECONFIG_REMOVE_PROPERTY: |
119 | prop = pr->prop; |
120 | break; |
121 | case OF_RECONFIG_UPDATE_PROPERTY: |
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 | |
184 | int of_property_notify(int action, struct device_node *np, |
185 | struct property *prop, struct property *oldprop) |
186 | { |
187 | struct of_reconfig_data pr; |
188 | |
189 | /* only call notifiers if the node is attached */ |
190 | if (!of_node_is_attached(node: np)) |
191 | return 0; |
192 | |
193 | pr.dn = np; |
194 | pr.prop = prop; |
195 | pr.old_prop = oldprop; |
196 | return of_reconfig_notify(action, p: &pr); |
197 | } |
198 | |
199 | static void __of_attach_node(struct device_node *np) |
200 | { |
201 | const __be32 *phandle; |
202 | int sz; |
203 | unsigned long flags; |
204 | |
205 | raw_spin_lock_irqsave(&devtree_lock, flags); |
206 | |
207 | if (!of_node_check_flag(n: np, OF_OVERLAY)) { |
208 | np->name = __of_get_property(np, name: "name" , NULL); |
209 | if (!np->name) |
210 | np->name = "<NULL>" ; |
211 | |
212 | phandle = __of_get_property(np, name: "phandle" , lenp: &sz); |
213 | if (!phandle) |
214 | phandle = __of_get_property(np, name: "linux,phandle" , lenp: &sz); |
215 | if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) |
216 | phandle = __of_get_property(np, name: "ibm,phandle" , lenp: &sz); |
217 | if (phandle && (sz >= 4)) |
218 | np->phandle = be32_to_cpup(p: phandle); |
219 | else |
220 | np->phandle = 0; |
221 | } |
222 | |
223 | np->child = NULL; |
224 | np->sibling = np->parent->child; |
225 | np->parent->child = np; |
226 | of_node_clear_flag(n: np, OF_DETACHED); |
227 | np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE; |
228 | |
229 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
230 | |
231 | __of_attach_node_sysfs(np); |
232 | } |
233 | |
234 | /** |
235 | * of_attach_node() - Plug a device node into the tree and global list. |
236 | * @np: Pointer to the caller's Device Node |
237 | */ |
238 | int of_attach_node(struct device_node *np) |
239 | { |
240 | struct of_reconfig_data rd; |
241 | |
242 | memset(&rd, 0, sizeof(rd)); |
243 | rd.dn = np; |
244 | |
245 | mutex_lock(&of_mutex); |
246 | __of_attach_node(np); |
247 | mutex_unlock(lock: &of_mutex); |
248 | |
249 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, p: &rd); |
250 | |
251 | return 0; |
252 | } |
253 | |
254 | void __of_detach_node(struct device_node *np) |
255 | { |
256 | struct device_node *parent; |
257 | unsigned long flags; |
258 | |
259 | raw_spin_lock_irqsave(&devtree_lock, flags); |
260 | |
261 | parent = np->parent; |
262 | if (WARN_ON(of_node_check_flag(np, OF_DETACHED) || !parent)) { |
263 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
264 | return; |
265 | } |
266 | |
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(n: np, OF_DETACHED); |
279 | |
280 | /* race with of_find_node_by_phandle() prevented by devtree_lock */ |
281 | __of_phandle_cache_inv_entry(handle: np->phandle); |
282 | |
283 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
284 | |
285 | __of_detach_node_sysfs(np); |
286 | } |
287 | |
288 | /** |
289 | * of_detach_node() - "Unplug" a node from the device tree. |
290 | * @np: Pointer to the caller's Device Node |
291 | */ |
292 | int of_detach_node(struct device_node *np) |
293 | { |
294 | struct of_reconfig_data rd; |
295 | |
296 | memset(&rd, 0, sizeof(rd)); |
297 | rd.dn = np; |
298 | |
299 | mutex_lock(&of_mutex); |
300 | __of_detach_node(np); |
301 | mutex_unlock(lock: &of_mutex); |
302 | |
303 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, p: &rd); |
304 | |
305 | return 0; |
306 | } |
307 | EXPORT_SYMBOL_GPL(of_detach_node); |
308 | |
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(objp: prop->name); |
316 | kfree(objp: prop->value); |
317 | kfree(objp: prop); |
318 | } |
319 | } |
320 | |
321 | /** |
322 | * of_node_release() - release a dynamically allocated node |
323 | * @kobj: kernel object of the node to be released |
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); |
330 | |
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 | |
337 | /* We should never be releasing nodes that haven't been detached. */ |
338 | if (!of_node_check_flag(n: node, OF_DETACHED)) { |
339 | |
340 | pr_err("ERROR: %s() detected bad of_node_put() on %pOF/%s\n" , |
341 | __func__, node->parent, node->full_name); |
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(); |
352 | pr_err("ERROR: next of_node_put() on this node will result in a kobject warning 'refcount_t: underflow; use-after-free.'\n" ); |
353 | } |
354 | |
355 | return; |
356 | } |
357 | if (!of_node_check_flag(n: node, OF_DYNAMIC)) |
358 | return; |
359 | |
360 | if (of_node_check_flag(n: node, OF_OVERLAY)) { |
361 | |
362 | if (!of_node_check_flag(n: 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 | |
379 | if (node->child) |
380 | pr_err("ERROR: %s() unexpected children for %pOF/%s\n" , |
381 | __func__, node->parent, node->full_name); |
382 | |
383 | property_list_free(prop_list: node->properties); |
384 | property_list_free(prop_list: node->deadprops); |
385 | fwnode_links_purge(of_fwnode_handle(node)); |
386 | |
387 | kfree(objp: node->full_name); |
388 | kfree(objp: node->data); |
389 | kfree(objp: node); |
390 | } |
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 |
398 | * property structure and the property name & contents. The property's |
399 | * flags have the OF_DYNAMIC bit set so that we can differentiate between |
400 | * dynamically allocated properties and not. |
401 | * |
402 | * Return: The newly allocated property or NULL on out of memory error. |
403 | */ |
404 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) |
405 | { |
406 | struct property *new; |
407 | |
408 | new = kzalloc(size: sizeof(*new), flags: allocflags); |
409 | if (!new) |
410 | return NULL; |
411 | |
412 | /* |
413 | * NOTE: There is no check for zero length value. |
414 | * In case of a boolean property, this will allocate a value |
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(s: prop->name, gfp: allocflags); |
419 | new->value = kmemdup(p: prop->value, size: prop->length, gfp: 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(p: new, OF_DYNAMIC); |
426 | |
427 | return new; |
428 | |
429 | err_free: |
430 | kfree(objp: new->name); |
431 | kfree(objp: new->value); |
432 | kfree(objp: new); |
433 | return NULL; |
434 | } |
435 | |
436 | /** |
437 | * __of_node_dup() - Duplicate or create an empty device node dynamically. |
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 |
440 | * |
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 | * |
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. |
447 | */ |
448 | struct device_node *__of_node_dup(const struct device_node *np, |
449 | const char *full_name) |
450 | { |
451 | struct device_node *node; |
452 | |
453 | node = kzalloc(size: sizeof(*node), GFP_KERNEL); |
454 | if (!node) |
455 | return NULL; |
456 | node->full_name = kstrdup(s: full_name, GFP_KERNEL); |
457 | if (!node->full_name) { |
458 | kfree(objp: node); |
459 | return NULL; |
460 | } |
461 | |
462 | of_node_set_flag(n: node, OF_DYNAMIC); |
463 | of_node_set_flag(n: node, OF_DETACHED); |
464 | of_node_init(node); |
465 | |
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(prop: pp, GFP_KERNEL); |
471 | if (!new_pp) |
472 | goto err_prop; |
473 | if (__of_add_property(np: node, prop: new_pp)) { |
474 | kfree(objp: new_pp->name); |
475 | kfree(objp: new_pp->value); |
476 | kfree(objp: new_pp); |
477 | goto err_prop; |
478 | } |
479 | } |
480 | } |
481 | return node; |
482 | |
483 | err_prop: |
484 | of_node_put(node); /* Frees the node and properties */ |
485 | return NULL; |
486 | } |
487 | |
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 | |
520 | static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) |
521 | { |
522 | if (ce->action == OF_RECONFIG_ATTACH_NODE && |
523 | of_node_check_flag(n: ce->np, OF_OVERLAY)) { |
524 | if (kref_read(kref: &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(n: ce->np, OF_OVERLAY_FREE_CSET); |
529 | } |
530 | } |
531 | |
532 | of_node_put(ce->np); |
533 | list_del(entry: &ce->node); |
534 | kfree(objp: ce); |
535 | } |
536 | |
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; |
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 | } |
563 | break; |
564 | } |
565 | } |
566 | |
567 | static int __of_changeset_entry_notify(struct of_changeset_entry *ce, |
568 | bool revert) |
569 | { |
570 | struct of_reconfig_data rd; |
571 | struct of_changeset_entry ce_inverted; |
572 | int ret = 0; |
573 | |
574 | if (revert) { |
575 | __of_changeset_entry_invert(ce, rce: &ce_inverted); |
576 | ce = &ce_inverted; |
577 | } |
578 | |
579 | switch (ce->action) { |
580 | case OF_RECONFIG_ATTACH_NODE: |
581 | case OF_RECONFIG_DETACH_NODE: |
582 | memset(&rd, 0, sizeof(rd)); |
583 | rd.dn = ce->np; |
584 | ret = of_reconfig_notify(action: ce->action, p: &rd); |
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(action: ce->action, np: ce->np, prop: ce->prop, oldprop: ce->old_prop); |
590 | break; |
591 | default: |
592 | pr_err("invalid devicetree changeset action: %i\n" , |
593 | (int)ce->action); |
594 | ret = -EINVAL; |
595 | } |
596 | |
597 | if (ret) |
598 | pr_err("changeset notifier error @%pOF\n" , ce->np); |
599 | return ret; |
600 | } |
601 | |
602 | static int __of_changeset_entry_apply(struct of_changeset_entry *ce) |
603 | { |
604 | int ret = 0; |
605 | |
606 | of_changeset_action_debug("apply: " , ce->action, ce->np, ce->prop); |
607 | |
608 | switch (ce->action) { |
609 | case OF_RECONFIG_ATTACH_NODE: |
610 | __of_attach_node(np: ce->np); |
611 | break; |
612 | case OF_RECONFIG_DETACH_NODE: |
613 | __of_detach_node(np: ce->np); |
614 | break; |
615 | case OF_RECONFIG_ADD_PROPERTY: |
616 | ret = __of_add_property(np: ce->np, prop: ce->prop); |
617 | break; |
618 | case OF_RECONFIG_REMOVE_PROPERTY: |
619 | ret = __of_remove_property(np: ce->np, prop: ce->prop); |
620 | break; |
621 | |
622 | case OF_RECONFIG_UPDATE_PROPERTY: |
623 | ret = __of_update_property(np: ce->np, newprop: ce->prop, oldprop: &ce->old_prop); |
624 | break; |
625 | default: |
626 | ret = -EINVAL; |
627 | } |
628 | |
629 | if (ret) { |
630 | of_changeset_action_err("apply failed: " , ce->action, ce->np, ce->prop); |
631 | return ret; |
632 | } |
633 | |
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, rce: &ce_inverted); |
642 | return __of_changeset_entry_apply(ce: &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(list: &ocs->entries); |
656 | } |
657 | EXPORT_SYMBOL_GPL(of_changeset_init); |
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 | |
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 | |
682 | list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node) |
683 | __of_changeset_entry_destroy(ce); |
684 | } |
685 | EXPORT_SYMBOL_GPL(of_changeset_destroy); |
686 | |
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) |
698 | { |
699 | struct of_changeset_entry *ce; |
700 | int ret, ret_tmp; |
701 | |
702 | pr_debug("changeset: applying...\n" ); |
703 | list_for_each_entry(ce, &ocs->entries, node) { |
704 | ret = __of_changeset_entry_apply(ce); |
705 | if (ret) { |
706 | pr_err("Error applying changeset (%d)\n" , ret); |
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 | } |
713 | return ret; |
714 | } |
715 | } |
716 | |
717 | return 0; |
718 | } |
719 | |
720 | /* |
721 | * Returns 0 on success, a negative error value in case of an error. |
722 | * |
723 | * If multiple changeset entry notification errors occur then only the |
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" ); |
732 | |
733 | /* drop the global lock while emitting notifiers */ |
734 | mutex_unlock(lock: &of_mutex); |
735 | list_for_each_entry(ce, &ocs->entries, node) { |
736 | ret_tmp = __of_changeset_entry_notify(ce, revert: 0); |
737 | if (ret_tmp) |
738 | ret = ret_tmp; |
739 | } |
740 | mutex_lock(&of_mutex); |
741 | pr_debug("changeset: notifiers sent.\n" ); |
742 | |
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: &ret_revert); |
759 | if (!ret) |
760 | ret = __of_changeset_apply_notify(ocs); |
761 | |
762 | return ret; |
763 | } |
764 | |
765 | /** |
766 | * of_changeset_apply - Applies a changeset |
767 | * |
768 | * @ocs: changeset pointer |
769 | * |
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. |
774 | * |
775 | * Return: 0 on success, a negative error value in case of an error. |
776 | * On error the partially applied effects are reverted. |
777 | */ |
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(lock: &of_mutex); |
785 | |
786 | return ret; |
787 | } |
788 | EXPORT_SYMBOL_GPL(of_changeset_apply); |
789 | |
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) |
802 | { |
803 | struct of_changeset_entry *ce; |
804 | int ret, ret_tmp; |
805 | |
806 | pr_debug("changeset: reverting...\n" ); |
807 | list_for_each_entry_reverse(ce, &ocs->entries, node) { |
808 | ret = __of_changeset_entry_revert(ce); |
809 | if (ret) { |
810 | pr_err("Error reverting changeset (%d)\n" , ret); |
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 | } |
816 | return ret; |
817 | } |
818 | } |
819 | |
820 | return 0; |
821 | } |
822 | |
823 | /* |
824 | * If multiple changeset entry notification errors occur then only the |
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" ); |
833 | |
834 | /* drop the global lock while emitting notifiers */ |
835 | mutex_unlock(lock: &of_mutex); |
836 | list_for_each_entry_reverse(ce, &ocs->entries, node) { |
837 | ret_tmp = __of_changeset_entry_notify(ce, revert: 1); |
838 | if (ret_tmp) |
839 | ret = ret_tmp; |
840 | } |
841 | mutex_lock(&of_mutex); |
842 | pr_debug("changeset: notifiers sent.\n" ); |
843 | |
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_apply: &ret_reply); |
853 | |
854 | if (!ret) |
855 | ret = __of_changeset_revert_notify(ocs); |
856 | |
857 | return ret; |
858 | } |
859 | |
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. |
869 | * |
870 | * Return: 0 on success, a negative error value in case of an error. |
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(lock: &of_mutex); |
879 | |
880 | return ret; |
881 | } |
882 | EXPORT_SYMBOL_GPL(of_changeset_revert); |
883 | |
884 | /** |
885 | * of_changeset_action - Add an action to the tail of the changeset list |
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 |
898 | * |
899 | * Return: 0 on success, a negative error value in case of an error. |
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 | |
906 | if (WARN_ON(action >= ARRAY_SIZE(action_names))) |
907 | return -EINVAL; |
908 | |
909 | ce = kzalloc(size: sizeof(*ce), GFP_KERNEL); |
910 | if (!ce) |
911 | return -ENOMEM; |
912 | |
913 | /* get a reference to the node */ |
914 | ce->action = action; |
915 | ce->np = of_node_get(np); |
916 | ce->prop = prop; |
917 | |
918 | /* add it to the list */ |
919 | list_add_tail(new: &ce->node, head: &ocs->entries); |
920 | return 0; |
921 | } |
922 | EXPORT_SYMBOL_GPL(of_changeset_action); |
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(prop: pp, GFP_KERNEL); |
932 | if (!new_pp) |
933 | return -ENOMEM; |
934 | |
935 | ret = of_changeset_add_property(ocs, np, prop: new_pp); |
936 | if (ret) { |
937 | kfree(objp: new_pp->name); |
938 | kfree(objp: new_pp->value); |
939 | kfree(objp: 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, pp: &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(size: 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(buf: vp, size: (char *)prop.value + prop.length - vp, fmt: "%s" , |
1007 | str_array[i]) + 1; |
1008 | } |
1009 | ret = of_changeset_add_prop_helper(ocs, np, pp: &prop); |
1010 | kfree(objp: 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(n: sz, size: 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, pp: &prop); |
1050 | kfree(objp: val); |
1051 | |
1052 | return ret; |
1053 | } |
1054 | EXPORT_SYMBOL_GPL(of_changeset_add_prop_u32_array); |
1055 | |