Lines Matching +full:pre +full:- +full:determined
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
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
78 /* flags are sticky - once set, do not reset */
125 * of_overlay_notifier_register() - Register notifier for overlay operations
143 * of_overlay_notifier_register() - Unregister notifier for overlay operations
153 "pre-apply",
154 "post-apply",
155 "pre-remove",
156 "post-remove",
165 for (i = 0; i < ovcs->count; i++) { in overlay_notify()
166 struct fragment *fragment = &ovcs->fragments[i]; in overlay_notify()
168 nd.target = fragment->target; in overlay_notify()
169 nd.overlay = fragment->overlay; in overlay_notify()
188 * the ovcs->overlay_tree. When duplicating the properties, the paths
193 * where symbol_path_tail can be a single node or it may be a multi-node path.
215 if (!prop->value) in dup_and_fixup_symbol_prop()
217 if (strnlen(prop->value, prop->length) >= prop->length) in dup_and_fixup_symbol_prop()
219 path = prop->value; in dup_and_fixup_symbol_prop()
224 fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1); in dup_and_fixup_symbol_prop()
229 for (k = 0; k < ovcs->count; k++) { in dup_and_fixup_symbol_prop()
230 fragment = &ovcs->fragments[k]; in dup_and_fixup_symbol_prop()
231 if (fragment->overlay == overlay_node) in dup_and_fixup_symbol_prop()
234 if (k >= ovcs->count) in dup_and_fixup_symbol_prop()
237 overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay); in dup_and_fixup_symbol_prop()
244 target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target); in dup_and_fixup_symbol_prop()
253 new_prop->name = kstrdup(prop->name, GFP_KERNEL); in dup_and_fixup_symbol_prop()
254 new_prop->length = target_path_len + path_tail_len + 1; in dup_and_fixup_symbol_prop()
255 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); in dup_and_fixup_symbol_prop()
256 if (!new_prop->name || !new_prop->value) in dup_and_fixup_symbol_prop()
259 strcpy(new_prop->value, target_path); in dup_and_fixup_symbol_prop()
260 strcpy(new_prop->value + target_path_len, path_tail); in dup_and_fixup_symbol_prop()
269 kfree(new_prop->name); in dup_and_fixup_symbol_prop()
270 kfree(new_prop->value); in dup_and_fixup_symbol_prop()
279 * add_changeset_property() - add @overlay_prop to overlay changeset
295 * Properties "#address-cells" and "#size-cells" are not updated if they
301 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
311 if (target->in_livetree) in add_changeset_property()
312 if (!of_prop_cmp(overlay_prop->name, "name") || in add_changeset_property()
313 !of_prop_cmp(overlay_prop->name, "phandle") || in add_changeset_property()
314 !of_prop_cmp(overlay_prop->name, "linux,phandle")) in add_changeset_property()
317 if (target->in_livetree) in add_changeset_property()
318 prop = of_find_property(target->np, overlay_prop->name, NULL); in add_changeset_property()
323 if (!of_prop_cmp(prop->name, "#address-cells")) { in add_changeset_property()
325 pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n", in add_changeset_property()
326 target->np); in add_changeset_property()
327 ret = -EINVAL; in add_changeset_property()
331 } else if (!of_prop_cmp(prop->name, "#size-cells")) { in add_changeset_property()
333 pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n", in add_changeset_property()
334 target->np); in add_changeset_property()
335 ret = -EINVAL; in add_changeset_property()
343 return -EINVAL; in add_changeset_property()
350 return -ENOMEM; in add_changeset_property()
353 if (!target->in_livetree) { in add_changeset_property()
354 new_prop->next = target->np->deadprops; in add_changeset_property()
355 target->np->deadprops = new_prop; in add_changeset_property()
357 ret = of_changeset_add_property(&ovcs->cset, target->np, in add_changeset_property()
360 ret = of_changeset_update_property(&ovcs->cset, target->np, in add_changeset_property()
364 if (!of_node_check_flag(target->np, OF_OVERLAY)) in add_changeset_property()
366 target->np, new_prop->name); in add_changeset_property()
369 kfree(new_prop->name); in add_changeset_property()
370 kfree(new_prop->value); in add_changeset_property()
377 * add_changeset_node() - add @node (and children) to overlay changeset
392 * not contain the full path in node->full_name. Thus an overlay
394 * node->full_name. However, a live devicetree created from Open
395 * Firmware may have the full path in node->full_name.
398 * the full path in node->full_name. Even though it expects the overlay
406 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
418 node_kbasename = kbasename(node->full_name); in add_changeset_node()
420 for_each_child_of_node(target->np, tchild) in add_changeset_node()
421 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) in add_changeset_node()
427 return -ENOMEM; in add_changeset_node()
429 tchild->parent = target->np; in add_changeset_node()
430 tchild->name = __of_get_property(node, "name", NULL); in add_changeset_node()
432 if (!tchild->name) in add_changeset_node()
433 tchild->name = "<NULL>"; in add_changeset_node()
438 tchild->phandle = be32_to_cpup(phandle); in add_changeset_node()
442 ret = of_changeset_attach_node(&ovcs->cset, tchild); in add_changeset_node()
454 if (node->phandle && tchild->phandle) { in add_changeset_node()
455 ret = -EINVAL; in add_changeset_node()
458 target_child.in_livetree = target->in_livetree; in add_changeset_node()
467 * build_changeset_next_level() - add level of overlay changeset
473 * @ovcs->cset changeset. If an added node has child nodes, they will
478 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
492 target->np, prop->name, ret); in build_changeset_next_level()
501 target->np, child, ret); in build_changeset_next_level()
511 * Add the properties from __overlay__ node to the @ovcs->cset changeset.
524 target->np, prop->name, ret); in build_changeset_symbols_node()
539 if (ce_1->action != OF_RECONFIG_ATTACH_NODE && in find_dup_cset_node_entry()
540 ce_1->action != OF_RECONFIG_DETACH_NODE) in find_dup_cset_node_entry()
544 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { in find_dup_cset_node_entry()
545 if ((ce_2->action != OF_RECONFIG_ATTACH_NODE && in find_dup_cset_node_entry()
546 ce_2->action != OF_RECONFIG_DETACH_NODE) || in find_dup_cset_node_entry()
547 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) in find_dup_cset_node_entry()
550 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); in find_dup_cset_node_entry()
551 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); in find_dup_cset_node_entry()
557 ce_1->np); in find_dup_cset_node_entry()
558 return -EINVAL; in find_dup_cset_node_entry()
572 if (ce_1->action != OF_RECONFIG_ADD_PROPERTY && in find_dup_cset_prop()
573 ce_1->action != OF_RECONFIG_REMOVE_PROPERTY && in find_dup_cset_prop()
574 ce_1->action != OF_RECONFIG_UPDATE_PROPERTY) in find_dup_cset_prop()
578 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { in find_dup_cset_prop()
579 if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY && in find_dup_cset_prop()
580 ce_2->action != OF_RECONFIG_REMOVE_PROPERTY && in find_dup_cset_prop()
581 ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) || in find_dup_cset_prop()
582 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) in find_dup_cset_prop()
585 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); in find_dup_cset_prop()
586 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); in find_dup_cset_prop()
591 !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) { in find_dup_cset_prop()
593 ce_1->np, ce_1->prop->name); in find_dup_cset_prop()
594 return -EINVAL; in find_dup_cset_prop()
602 * changeset_dup_entry_check() - check for duplicate entries
605 * Check changeset @ovcs->cset for multiple {add or delete} node entries for
609 * Returns 0 on success, or -EINVAL if duplicate changeset entry found.
616 list_for_each_entry(ce_1, &ovcs->cset.entries, node) { in changeset_dup_entry_check()
621 return dup_entry ? -EINVAL : 0; in changeset_dup_entry_check()
625 * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments
628 * Create changeset @ovcs->cset to contain the nodes and properties of the
629 * overlay device tree fragments in @ovcs->fragments[]. If an error occurs,
631 * in @ovcs->cset.
633 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
634 * invalid overlay in @ovcs->fragments[].
643 * if there is a symbols fragment in ovcs->fragments[i] it is in build_changeset()
646 if (ovcs->symbols_fragment) in build_changeset()
647 fragments_count = ovcs->count - 1; in build_changeset()
649 fragments_count = ovcs->count; in build_changeset()
652 fragment = &ovcs->fragments[i]; in build_changeset()
654 target.np = fragment->target; in build_changeset()
657 fragment->overlay); in build_changeset()
660 fragment->target); in build_changeset()
665 if (ovcs->symbols_fragment) { in build_changeset()
666 fragment = &ovcs->fragments[ovcs->count - 1]; in build_changeset()
668 target.np = fragment->target; in build_changeset()
671 fragment->overlay); in build_changeset()
674 fragment->target); in build_changeset()
687 * 2) "target-path" property containing the path of the target
705 ret = of_property_read_string(info_node, "target-path", &path); in find_target()
720 * init_overlay_changeset() - initialize overlay changeset from overlay tree
725 * Initialize @ovcs. Populate @ovcs->fragments with node information from
729 * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
730 * detected in @tree, or -ENOSPC if idr_alloc() error.
741 * Warn for some issues. Can not return -EINVAL for these until in init_overlay_changeset()
753 ovcs->overlay_tree = tree; in init_overlay_changeset()
754 ovcs->fdt = fdt; in init_overlay_changeset()
756 INIT_LIST_HEAD(&ovcs->ovcs_list); in init_overlay_changeset()
758 of_changeset_init(&ovcs->cset); in init_overlay_changeset()
783 ret = -ENOMEM; in init_overlay_changeset()
794 fragment->overlay = overlay_node; in init_overlay_changeset()
795 fragment->target = find_target(node); in init_overlay_changeset()
796 if (!fragment->target) { in init_overlay_changeset()
797 of_node_put(fragment->overlay); in init_overlay_changeset()
798 ret = -EINVAL; in init_overlay_changeset()
806 * if there is a symbols fragment in ovcs->fragments[i] it is in init_overlay_changeset()
811 ovcs->symbols_fragment = 1; in init_overlay_changeset()
813 fragment->overlay = node; in init_overlay_changeset()
814 fragment->target = of_find_node_by_path("/__symbols__"); in init_overlay_changeset()
816 if (!fragment->target) { in init_overlay_changeset()
818 ret = -EINVAL; in init_overlay_changeset()
827 ret = -EINVAL; in init_overlay_changeset()
831 ovcs->id = id; in init_overlay_changeset()
832 ovcs->count = cnt; in init_overlay_changeset()
833 ovcs->fragments = fragments; in init_overlay_changeset()
851 if (ovcs->cset.entries.next) in free_overlay_changeset()
852 of_changeset_destroy(&ovcs->cset); in free_overlay_changeset()
854 if (ovcs->id) in free_overlay_changeset()
855 idr_remove(&ovcs_idr, ovcs->id); in free_overlay_changeset()
857 for (i = 0; i < ovcs->count; i++) { in free_overlay_changeset()
858 of_node_put(ovcs->fragments[i].target); in free_overlay_changeset()
859 of_node_put(ovcs->fragments[i].overlay); in free_overlay_changeset()
861 kfree(ovcs->fragments); in free_overlay_changeset()
863 * There should be no live pointers into ovcs->overlay_tree and in free_overlay_changeset()
864 * ovcs->fdt due to the policy that overlay notifiers are not allowed in free_overlay_changeset()
867 kfree(ovcs->overlay_tree); in free_overlay_changeset()
868 kfree(ovcs->fdt); in free_overlay_changeset()
875 * of_overlay_apply() - Create and apply an overlay changeset
882 * If an error occurs in a pre-apply notifier, then no changes are made
886 * A non-zero return value will not have created the changeset if error is from:
887 * - parameter checks
888 * - building the changeset
889 * - overlay changeset pre-apply notifier
891 * If an error is returned by an overlay changeset pre-apply notifier
892 * then no further overlay changeset pre-apply notifier will be called.
894 * A non-zero return value will have created the changeset if error is from:
895 * - overlay changeset entry notifier
896 * - overlay changeset post-apply notifier
898 * If an error is returned by an overlay changeset post-apply notifier
899 * then no further overlay changeset post-apply notifier will be called.
907 * then the state of the device tree can not be determined, and any
930 ret = -EBUSY; in of_overlay_apply()
938 ret = -ENOMEM; in of_overlay_apply()
954 * after overlay_notify(), ovcs->overlay_tree related pointers may have in of_overlay_apply()
955 * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree; in of_overlay_apply()
956 * and can not free fdt, aka ovcs->fdt in of_overlay_apply()
960 pr_err("overlay changeset pre-apply notify error %d\n", ret); in of_overlay_apply()
969 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert); in of_overlay_apply()
979 ret = __of_changeset_apply_notify(&ovcs->cset); in of_overlay_apply()
984 list_add_tail(&ovcs->ovcs_list, &ovcs_list); in of_overlay_apply()
985 *ovcs_id = ovcs->id; in of_overlay_apply()
989 pr_err("overlay changeset post-apply notify error %d\n", in of_overlay_apply()
1028 return -EINVAL; in of_overlay_fdt_apply()
1033 return -EINVAL; in of_overlay_fdt_apply()
1041 return -ENOMEM; in of_overlay_fdt_apply()
1046 ret = -EINVAL; in of_overlay_fdt_apply()
1109 list_for_each_entry(ce, &ovcs->cset.entries, node) { in node_overlaps_later_cs()
1110 if (find_node(ce->np, remove_ce_node)) { in node_overlaps_later_cs()
1112 __func__, remove_ovcs->id, ovcs->id, in node_overlaps_later_cs()
1116 if (find_node(remove_ce_node, ce->np)) { in node_overlaps_later_cs()
1118 __func__, remove_ovcs->id, ovcs->id, in node_overlaps_later_cs()
1129 * We can safely remove the overlay only if it's the top-most one.
1142 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) { in overlay_removal_is_ok()
1143 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) { in overlay_removal_is_ok()
1144 pr_err("overlay #%d is not topmost\n", remove_ovcs->id); in overlay_removal_is_ok()
1153 * of_overlay_remove() - Revert and free an overlay changeset
1160 * then an attempt is made to re-apply any changeset entry that was
1161 * reverted. If an error occurs on re-apply then the state of the device
1162 * tree can not be determined, and any following attempt to apply or remove
1165 * A non-zero return value will not revert the changeset if error is from:
1166 * - parameter checks
1167 * - overlay changeset pre-remove notifier
1168 * - overlay changeset entry revert
1170 * If an error is returned by an overlay changeset pre-remove notifier
1171 * then no further overlay changeset pre-remove notifier will be called.
1176 * A non-zero return value will revert the changeset if error is from:
1177 * - overlay changeset entry notifier
1178 * - overlay changeset post-remove notifier
1180 * If an error is returned by an overlay changeset post-remove notifier
1181 * then no further overlay changeset post-remove notifier will be called.
1195 ret = -EBUSY; in of_overlay_remove()
1203 ret = -ENODEV; in of_overlay_remove()
1209 ret = -EBUSY; in of_overlay_remove()
1215 pr_err("overlay changeset pre-remove notify error %d\n", ret); in of_overlay_remove()
1219 list_del(&ovcs->ovcs_list); in of_overlay_remove()
1222 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply); in of_overlay_remove()
1229 ret = __of_changeset_revert_notify(&ovcs->cset); in of_overlay_remove()
1238 pr_err("overlay changeset post-remove notify error %d\n", in of_overlay_remove()
1257 * of_overlay_remove_all() - Reverts and frees all overlay changesets
1270 ret = of_overlay_remove(&ovcs->id); in of_overlay_remove_all()