Lines Matching +full:non +full:- +full:live
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
27 * struct target - info about current target node as recursing through overlay
29 * @in_livetree: @np is a node in the live devicetree
33 * in the live devicetree where the overlay subtree is targeted to be grafted
35 * also recurses to the next level of the live devicetree, as long as overlay
36 * subtree node also exists in the live devicetree. When a node in the overlay
37 * subtree does not exist at the same level in the live devicetree, target->np
47 * struct fragment - info about fragment nodes in overlay expanded device tree
67 * @cset: changeset to apply fragments to live device tree
82 /* flags are sticky - once set, do not reset */
102 * of_resolve_phandles() finds the largest phandle in the live tree.
103 * of_overlay_apply() may add a larger phandle to the live tree.
128 * of_overlay_notifier_register() - Register notifier for overlay operations
146 * of_overlay_notifier_unregister() - Unregister notifier for overlay operations
161 ovcs->notify_state = action; in overlay_notify()
163 for (i = 0; i < ovcs->count; i++) { in overlay_notify()
164 struct fragment *fragment = &ovcs->fragments[i]; in overlay_notify()
166 nd.target = fragment->target; in overlay_notify()
167 nd.overlay = fragment->overlay; in overlay_notify()
184 * the ovcs->overlay_root. When duplicating the properties, the paths
185 * need to be adjusted to be the correct path for the live device tree.
189 * where symbol_path_tail can be a single node or it may be a multi-node path.
211 if (!prop->value) in dup_and_fixup_symbol_prop()
213 if (strnlen(prop->value, prop->length) >= prop->length) in dup_and_fixup_symbol_prop()
215 path = prop->value; in dup_and_fixup_symbol_prop()
220 fragment_node = __of_find_node_by_path(ovcs->overlay_root, path + 1); in dup_and_fixup_symbol_prop()
225 for (k = 0; k < ovcs->count; k++) { in dup_and_fixup_symbol_prop()
226 fragment = &ovcs->fragments[k]; in dup_and_fixup_symbol_prop()
227 if (fragment->overlay == overlay_node) in dup_and_fixup_symbol_prop()
230 if (k >= ovcs->count) in dup_and_fixup_symbol_prop()
233 overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay); in dup_and_fixup_symbol_prop()
240 target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target); in dup_and_fixup_symbol_prop()
249 new_prop->name = kstrdup(prop->name, GFP_KERNEL); in dup_and_fixup_symbol_prop()
250 new_prop->length = target_path_len + path_tail_len + 1; in dup_and_fixup_symbol_prop()
251 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); in dup_and_fixup_symbol_prop()
252 if (!new_prop->name || !new_prop->value) in dup_and_fixup_symbol_prop()
255 strcpy(new_prop->value, target_path); in dup_and_fixup_symbol_prop()
256 strcpy(new_prop->value + target_path_len, path_tail); in dup_and_fixup_symbol_prop()
273 * add_changeset_property() - add @overlay_prop to overlay changeset
279 * If @overlay_prop does not already exist in live devicetree, add changeset
283 * @target may be either in the live devicetree or in a new subtree that
289 * Properties "#address-cells" and "#size-cells" are not updated if they
290 * are already in the live tree, but if present in the live tree, the values
291 * in the overlay must match the values in the live tree.
295 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
306 if (target->in_livetree) in add_changeset_property()
307 if (!of_prop_cmp(overlay_prop->name, "name") || in add_changeset_property()
308 !of_prop_cmp(overlay_prop->name, "phandle") || in add_changeset_property()
309 !of_prop_cmp(overlay_prop->name, "linux,phandle")) in add_changeset_property()
312 if (target->in_livetree) in add_changeset_property()
313 prop = of_find_property(target->np, overlay_prop->name, NULL); in add_changeset_property()
318 if (!of_prop_cmp(prop->name, "#address-cells")) { in add_changeset_property()
320 pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n", in add_changeset_property()
321 target->np); in add_changeset_property()
322 ret = -EINVAL; in add_changeset_property()
326 } else if (!of_prop_cmp(prop->name, "#size-cells")) { in add_changeset_property()
328 pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n", in add_changeset_property()
329 target->np); in add_changeset_property()
330 ret = -EINVAL; in add_changeset_property()
338 return -EINVAL; in add_changeset_property()
345 return -ENOMEM; in add_changeset_property()
348 if (!target->in_livetree) { in add_changeset_property()
349 new_prop->next = target->np->deadprops; in add_changeset_property()
350 target->np->deadprops = new_prop; in add_changeset_property()
352 ret = of_changeset_add_property(&ovcs->cset, target->np, in add_changeset_property()
355 ret = of_changeset_update_property(&ovcs->cset, target->np, in add_changeset_property()
359 if (!of_node_check_flag(target->np, OF_OVERLAY)) in add_changeset_property()
361 target->np, new_prop->name); in add_changeset_property()
369 * add_changeset_node() - add @node (and children) to overlay changeset
371 * @target: where @node will be placed in live tree or changeset
383 * NOTE_1: A live devicetree created from a flattened device tree (FDT) will
384 * not contain the full path in node->full_name. Thus an overlay
386 * node->full_name. However, a live devicetree created from Open
387 * Firmware may have the full path in node->full_name.
390 * the full path in node->full_name. Even though it expects the overlay
393 * to nodes in the live devicetree so that it can apply an overlay to
394 * a live devicetree created from Open Firmware.
398 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
410 node_kbasename = kbasename(node->full_name); in add_changeset_node()
412 for_each_child_of_node(target->np, tchild) in add_changeset_node()
413 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) in add_changeset_node()
419 return -ENOMEM; in add_changeset_node()
421 tchild->parent = target->np; in add_changeset_node()
422 tchild->name = __of_get_property(node, "name", NULL); in add_changeset_node()
424 if (!tchild->name) in add_changeset_node()
425 tchild->name = "<NULL>"; in add_changeset_node()
430 tchild->phandle = be32_to_cpup(phandle); in add_changeset_node()
434 ret = of_changeset_attach_node(&ovcs->cset, tchild); in add_changeset_node()
446 if (node->phandle && tchild->phandle) { in add_changeset_node()
447 ret = -EINVAL; in add_changeset_node()
450 target_child.in_livetree = target->in_livetree; in add_changeset_node()
459 * build_changeset_next_level() - add level of overlay changeset
461 * @target: where to place @overlay_node in live tree
465 * @ovcs->cset changeset. If an added node has child nodes, they will
470 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
483 target->np, prop->name, ret); in build_changeset_next_level()
492 target->np, child, ret); in build_changeset_next_level()
501 * Add the properties from __overlay__ node to the @ovcs->cset changeset.
514 target->np, prop->name, ret); in build_changeset_symbols_node()
529 if (ce_1->action != OF_RECONFIG_ATTACH_NODE && in find_dup_cset_node_entry()
530 ce_1->action != OF_RECONFIG_DETACH_NODE) in find_dup_cset_node_entry()
534 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { in find_dup_cset_node_entry()
535 if ((ce_2->action != OF_RECONFIG_ATTACH_NODE && in find_dup_cset_node_entry()
536 ce_2->action != OF_RECONFIG_DETACH_NODE) || in find_dup_cset_node_entry()
537 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) in find_dup_cset_node_entry()
540 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); in find_dup_cset_node_entry()
541 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); in find_dup_cset_node_entry()
547 ce_1->np); in find_dup_cset_node_entry()
548 return -EINVAL; in find_dup_cset_node_entry()
562 if (ce_1->action != OF_RECONFIG_ADD_PROPERTY && in find_dup_cset_prop()
563 ce_1->action != OF_RECONFIG_REMOVE_PROPERTY && in find_dup_cset_prop()
564 ce_1->action != OF_RECONFIG_UPDATE_PROPERTY) in find_dup_cset_prop()
568 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { in find_dup_cset_prop()
569 if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY && in find_dup_cset_prop()
570 ce_2->action != OF_RECONFIG_REMOVE_PROPERTY && in find_dup_cset_prop()
571 ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) || in find_dup_cset_prop()
572 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) in find_dup_cset_prop()
575 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); in find_dup_cset_prop()
576 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); in find_dup_cset_prop()
581 !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) { in find_dup_cset_prop()
583 ce_1->np, ce_1->prop->name); in find_dup_cset_prop()
584 return -EINVAL; in find_dup_cset_prop()
592 * changeset_dup_entry_check() - check for duplicate entries
595 * Check changeset @ovcs->cset for multiple {add or delete} node entries for
599 * Return: 0 on success, or -EINVAL if duplicate changeset entry found.
606 list_for_each_entry(ce_1, &ovcs->cset.entries, node) { in changeset_dup_entry_check()
611 return dup_entry ? -EINVAL : 0; in changeset_dup_entry_check()
615 * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments
618 * Create changeset @ovcs->cset to contain the nodes and properties of the
619 * overlay device tree fragments in @ovcs->fragments[]. If an error occurs,
621 * in @ovcs->cset.
623 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
624 * invalid overlay in @ovcs->fragments[].
633 * if there is a symbols fragment in ovcs->fragments[i] it is in build_changeset()
636 if (ovcs->symbols_fragment) in build_changeset()
637 fragments_count = ovcs->count - 1; in build_changeset()
639 fragments_count = ovcs->count; in build_changeset()
642 fragment = &ovcs->fragments[i]; in build_changeset()
644 target.np = fragment->target; in build_changeset()
647 fragment->overlay); in build_changeset()
650 fragment->target); in build_changeset()
655 if (ovcs->symbols_fragment) { in build_changeset()
656 fragment = &ovcs->fragments[ovcs->count - 1]; in build_changeset()
658 target.np = fragment->target; in build_changeset()
661 fragment->overlay); in build_changeset()
664 fragment->target); in build_changeset()
677 * 2) "target-path" property containing the path of the target
697 ret = of_property_read_string(info_node, "target-path", &path); in find_target()
725 * init_overlay_changeset() - initialize overlay changeset from overlay tree
729 * Initialize @ovcs. Populate @ovcs->fragments with node information from
734 * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
754 * Warn for some issues. Can not return -EINVAL for these until in init_overlay_changeset()
757 if (!of_node_check_flag(ovcs->overlay_root, OF_DYNAMIC)) in init_overlay_changeset()
758 pr_debug("%s() ovcs->overlay_root is not dynamic\n", __func__); in init_overlay_changeset()
760 if (!of_node_check_flag(ovcs->overlay_root, OF_DETACHED)) in init_overlay_changeset()
761 pr_debug("%s() ovcs->overlay_root is not detached\n", __func__); in init_overlay_changeset()
763 if (!of_node_is_root(ovcs->overlay_root)) in init_overlay_changeset()
764 pr_debug("%s() ovcs->overlay_root is not root\n", __func__); in init_overlay_changeset()
769 for_each_child_of_node(ovcs->overlay_root, node) { in init_overlay_changeset()
777 node = of_get_child_by_name(ovcs->overlay_root, "__symbols__"); in init_overlay_changeset()
785 ret = -ENOMEM; in init_overlay_changeset()
788 ovcs->fragments = fragments; in init_overlay_changeset()
791 for_each_child_of_node(ovcs->overlay_root, node) { in init_overlay_changeset()
797 fragment->overlay = overlay_node; in init_overlay_changeset()
798 fragment->target = find_target(node, target_base); in init_overlay_changeset()
799 if (!fragment->target) { in init_overlay_changeset()
800 of_node_put(fragment->overlay); in init_overlay_changeset()
801 ret = -EINVAL; in init_overlay_changeset()
810 * if there is a symbols fragment in ovcs->fragments[i] it is in init_overlay_changeset()
813 node = of_get_child_by_name(ovcs->overlay_root, "__symbols__"); in init_overlay_changeset()
815 ovcs->symbols_fragment = 1; in init_overlay_changeset()
817 fragment->overlay = node; in init_overlay_changeset()
818 fragment->target = of_find_node_by_path("/__symbols__"); in init_overlay_changeset()
820 if (!fragment->target) { in init_overlay_changeset()
821 pr_err("symbols in overlay, but not in live tree\n"); in init_overlay_changeset()
822 ret = -EINVAL; in init_overlay_changeset()
832 ret = -EINVAL; in init_overlay_changeset()
836 ovcs->count = cnt; in init_overlay_changeset()
850 if (ovcs->cset.entries.next) in free_overlay_changeset()
851 of_changeset_destroy(&ovcs->cset); in free_overlay_changeset()
853 if (ovcs->id) { in free_overlay_changeset()
854 idr_remove(&ovcs_idr, ovcs->id); in free_overlay_changeset()
855 list_del(&ovcs->ovcs_list); in free_overlay_changeset()
856 ovcs->id = 0; in free_overlay_changeset()
860 for (i = 0; i < ovcs->count; i++) { in free_overlay_changeset()
861 of_node_put(ovcs->fragments[i].target); in free_overlay_changeset()
862 of_node_put(ovcs->fragments[i].overlay); in free_overlay_changeset()
864 kfree(ovcs->fragments); in free_overlay_changeset()
867 * There should be no live pointers into ovcs->overlay_mem and in free_overlay_changeset()
868 * ovcs->new_fdt due to the policy that overlay notifiers are not in free_overlay_changeset()
876 if (ovcs->notify_state == OF_OVERLAY_INIT || in free_overlay_changeset()
877 ovcs->notify_state == OF_OVERLAY_POST_REMOVE) { in free_overlay_changeset()
878 kfree(ovcs->overlay_mem); in free_overlay_changeset()
879 kfree(ovcs->new_fdt); in free_overlay_changeset()
887 * of_overlay_apply() - Create and apply an overlay changeset
893 * If an error is returned by an overlay changeset pre-apply notifier
894 * then no further overlay changeset pre-apply notifier will be called.
896 * If an error is returned by an overlay changeset post-apply notifier
897 * then no further overlay changeset post-apply notifier will be called.
918 ret = of_resolve_phandles(ovcs->overlay_root); in of_overlay_apply()
935 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert); in of_overlay_apply()
945 ret = __of_changeset_apply_notify(&ovcs->cset); in of_overlay_apply()
962 * of_overlay_fdt_apply() - Create and apply an overlay changeset
995 return -EBUSY; in of_overlay_fdt_apply()
1001 return -EINVAL; in of_overlay_fdt_apply()
1006 return -EINVAL; in of_overlay_fdt_apply()
1010 return -ENOMEM; in of_overlay_fdt_apply()
1016 * ovcs->notify_state must be set to OF_OVERLAY_INIT before allocating in of_overlay_fdt_apply()
1020 ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL); in of_overlay_fdt_apply()
1021 if (ovcs->id <= 0) { in of_overlay_fdt_apply()
1022 ret = ovcs->id; in of_overlay_fdt_apply()
1026 INIT_LIST_HEAD(&ovcs->ovcs_list); in of_overlay_fdt_apply()
1027 list_add_tail(&ovcs->ovcs_list, &ovcs_list); in of_overlay_fdt_apply()
1028 of_changeset_init(&ovcs->cset); in of_overlay_fdt_apply()
1036 ret = -ENOMEM; in of_overlay_fdt_apply()
1039 ovcs->new_fdt = new_fdt; in of_overlay_fdt_apply()
1045 &ovcs->overlay_root); in of_overlay_fdt_apply()
1048 ret = -EINVAL; in of_overlay_fdt_apply()
1051 ovcs->overlay_mem = overlay_mem; in of_overlay_fdt_apply()
1060 *ret_ovcs_id = ovcs->id; in of_overlay_fdt_apply()
1107 list_for_each_entry(ce, &ovcs->cset.entries, node) { in node_overlaps_later_cs()
1108 if (find_node(ce->np, remove_ce_node)) { in node_overlaps_later_cs()
1110 __func__, remove_ovcs->id, ovcs->id, in node_overlaps_later_cs()
1114 if (find_node(remove_ce_node, ce->np)) { in node_overlaps_later_cs()
1116 __func__, remove_ovcs->id, ovcs->id, in node_overlaps_later_cs()
1127 * We can safely remove the overlay only if it's the top-most one.
1140 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) { in overlay_removal_is_ok()
1141 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) { in overlay_removal_is_ok()
1142 pr_err("overlay #%d is not topmost\n", remove_ovcs->id); in overlay_removal_is_ok()
1151 * of_overlay_remove() - Revert and free an overlay changeset
1158 * then an attempt is made to re-apply any changeset entry that was
1159 * reverted. If an error occurs on re-apply then the state of the device
1163 * A non-zero return value will not revert the changeset if error is from:
1164 * - parameter checks
1165 * - overlay changeset pre-remove notifier
1166 * - overlay changeset entry revert
1168 * If an error is returned by an overlay changeset pre-remove notifier
1169 * then no further overlay changeset pre-remove notifier will be called.
1174 * A non-zero return value will revert the changeset if error is from:
1175 * - overlay changeset entry notifier
1176 * - overlay changeset post-remove notifier
1178 * If an error is returned by an overlay changeset post-remove notifier
1179 * then no further overlay changeset post-remove notifier will be called.
1191 ret = -EBUSY; in of_overlay_remove()
1199 ret = -ENODEV; in of_overlay_remove()
1205 ret = -EBUSY; in of_overlay_remove()
1214 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply); in of_overlay_remove()
1221 ret = __of_changeset_revert_notify(&ovcs->cset); in of_overlay_remove()
1256 * of_overlay_remove_all() - Reverts and frees all overlay changesets
1269 ret = of_overlay_remove(&ovcs->id); in of_overlay_remove_all()