Lines Matching +full:i +full:- +full:leak +full:- +full:current

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
28 * @np: node where current level of overlay will be applied
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
82 /* flags are sticky - once set, do not reset */
89 return p1->length == p2->length &&
90 !memcmp(p1->value, p2->value, (size_t)p1->length);
134 * of_overlay_notifier_register() - Register notifier for overlay operations
152 * of_overlay_notifier_unregister() - Unregister notifier for overlay operations
165 int i, ret;
167 ovcs->notify_state = action;
169 for (i = 0; i < ovcs->count; i++) {
170 struct fragment *fragment = &ovcs->fragments[i];
172 nd.target = fragment->target;
173 nd.overlay = fragment->overlay;
190 * the ovcs->overlay_root. When duplicating the properties, the paths
195 * where symbol_path_tail can be a single node or it may be a multi-node path.
217 if (!prop->value)
219 if (strnlen(prop->value, prop->length) >= prop->length)
221 path = prop->value;
226 fragment_node = __of_find_node_by_path(ovcs->overlay_root, path + 1);
231 for (k = 0; k < ovcs->count; k++) {
232 fragment = &ovcs->fragments[k];
233 if (fragment->overlay == overlay_node)
236 if (k >= ovcs->count)
239 overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay);
246 target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target);
255 new_prop->name = kstrdup(prop->name, GFP_KERNEL);
256 new_prop->length = target_path_len + path_tail_len + 1;
257 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
258 if (!new_prop->name || !new_prop->value)
261 strcpy(new_prop->value, target_path);
262 strcpy(new_prop->value + target_path_len, path_tail);
279 * add_changeset_property() - add @overlay_prop to overlay changeset
295 * Properties "#address-cells" and "#size-cells" are not updated if they
301 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
312 if (target->in_livetree)
313 if (is_pseudo_property(overlay_prop->name))
316 if (target->in_livetree)
317 prop = of_find_property(target->np, overlay_prop->name, NULL);
322 if (!of_prop_cmp(prop->name, "#address-cells")) {
324 pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
325 target->np);
326 ret = -EINVAL;
330 } else if (!of_prop_cmp(prop->name, "#size-cells")) {
332 pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
333 target->np);
334 ret = -EINVAL;
342 return -EINVAL;
349 return -ENOMEM;
352 if (!target->in_livetree) {
353 new_prop->next = target->np->deadprops;
354 target->np->deadprops = new_prop;
356 ret = of_changeset_add_property(&ovcs->cset, target->np,
359 ret = of_changeset_update_property(&ovcs->cset, target->np,
363 if (!of_node_check_flag(target->np, OF_OVERLAY))
364 pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
365 target->np, new_prop->name);
373 * add_changeset_node() - add @node (and children) to overlay changeset
388 * not contain the full path in node->full_name. Thus an overlay
390 * node->full_name. However, a live devicetree created from Open
391 * Firmware may have the full path in node->full_name.
394 * the full path in node->full_name. Even though it expects the overlay
402 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
414 node_kbasename = kbasename(node->full_name);
416 for_each_child_of_node(target->np, tchild)
417 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
423 return -ENOMEM;
425 tchild->parent = target->np;
426 tchild->name = __of_get_property(node, "name", NULL);
428 if (!tchild->name)
429 tchild->name = "<NULL>";
434 tchild->phandle = be32_to_cpup(phandle);
438 ret = of_changeset_attach_node(&ovcs->cset, tchild);
450 if (node->phandle && tchild->phandle) {
451 ret = -EINVAL;
454 target_child.in_livetree = target->in_livetree;
463 * build_changeset_next_level() - add level of overlay changeset
469 * @ovcs->cset changeset. If an added node has child nodes, they will
474 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
487 target->np, prop->name, ret);
496 target->np, child, ret);
505 * Add the properties from __overlay__ node to the @ovcs->cset changeset.
518 target->np, prop->name, ret);
533 if (ce_1->action != OF_RECONFIG_ATTACH_NODE &&
534 ce_1->action != OF_RECONFIG_DETACH_NODE)
538 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
539 if ((ce_2->action != OF_RECONFIG_ATTACH_NODE &&
540 ce_2->action != OF_RECONFIG_DETACH_NODE) ||
541 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
544 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
545 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
551 ce_1->np);
552 return -EINVAL;
566 if (ce_1->action != OF_RECONFIG_ADD_PROPERTY &&
567 ce_1->action != OF_RECONFIG_REMOVE_PROPERTY &&
568 ce_1->action != OF_RECONFIG_UPDATE_PROPERTY)
572 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
573 if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY &&
574 ce_2->action != OF_RECONFIG_REMOVE_PROPERTY &&
575 ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) ||
576 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
579 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
580 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
585 !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) {
587 ce_1->np, ce_1->prop->name);
588 return -EINVAL;
596 * changeset_dup_entry_check() - check for duplicate entries
599 * Check changeset @ovcs->cset for multiple {add or delete} node entries for
603 * Return: 0 on success, or -EINVAL if duplicate changeset entry found.
610 list_for_each_entry(ce_1, &ovcs->cset.entries, node) {
615 return dup_entry ? -EINVAL : 0;
619 * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments
622 * Create changeset @ovcs->cset to contain the nodes and properties of the
623 * overlay device tree fragments in @ovcs->fragments[]. If an error occurs,
625 * in @ovcs->cset.
627 * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
628 * invalid overlay in @ovcs->fragments[].
634 int fragments_count, i, ret;
637 * if there is a symbols fragment in ovcs->fragments[i] it is
640 if (ovcs->symbols_fragment)
641 fragments_count = ovcs->count - 1;
643 fragments_count = ovcs->count;
645 for (i = 0; i < fragments_count; i++) {
646 fragment = &ovcs->fragments[i];
648 target.np = fragment->target;
651 fragment->overlay);
654 fragment->target);
659 if (ovcs->symbols_fragment) {
660 fragment = &ovcs->fragments[ovcs->count - 1];
662 target.np = fragment->target;
665 fragment->overlay);
668 fragment->target);
681 * 2) "target-path" property containing the path of the target
701 ret = of_property_read_string(info_node, "target-path", &path);
729 * init_overlay_changeset() - initialize overlay changeset from overlay tree
733 * Initialize @ovcs. Populate @ovcs->fragments with node information from
738 * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
758 * Warn for some issues. Can not return -EINVAL for these until
761 if (!of_node_check_flag(ovcs->overlay_root, OF_DYNAMIC))
762 pr_debug("%s() ovcs->overlay_root is not dynamic\n", __func__);
764 if (!of_node_check_flag(ovcs->overlay_root, OF_DETACHED))
765 pr_debug("%s() ovcs->overlay_root is not detached\n", __func__);
767 if (!of_node_is_root(ovcs->overlay_root))
768 pr_debug("%s() ovcs->overlay_root is not root\n", __func__);
773 for_each_child_of_node(ovcs->overlay_root, node) {
781 node = of_get_child_by_name(ovcs->overlay_root, "__symbols__");
789 ret = -ENOMEM;
792 ovcs->fragments = fragments;
795 for_each_child_of_node(ovcs->overlay_root, node) {
801 fragment->overlay = overlay_node;
802 fragment->target = find_target(node, target_base);
803 if (!fragment->target) {
804 of_node_put(fragment->overlay);
805 ret = -EINVAL;
814 * if there is a symbols fragment in ovcs->fragments[i] it is
817 node = of_get_child_by_name(ovcs->overlay_root, "__symbols__");
819 ovcs->symbols_fragment = 1;
821 fragment->overlay = node;
822 fragment->target = of_find_node_by_path("/__symbols__");
824 if (!fragment->target) {
826 ret = -EINVAL;
836 ret = -EINVAL;
840 ovcs->count = cnt;
852 int i;
854 if (ovcs->cset.entries.next)
855 of_changeset_destroy(&ovcs->cset);
857 if (ovcs->id) {
858 idr_remove(&ovcs_idr, ovcs->id);
859 list_del(&ovcs->ovcs_list);
860 ovcs->id = 0;
864 for (i = 0; i < ovcs->count; i++) {
865 of_node_put(ovcs->fragments[i].target);
866 of_node_put(ovcs->fragments[i].overlay);
868 kfree(ovcs->fragments);
871 * There should be no live pointers into ovcs->overlay_mem and
872 * ovcs->new_fdt due to the policy that overlay notifiers are not
877 * A memory leak will occur here if within the window.
880 if (ovcs->notify_state == OF_OVERLAY_INIT ||
881 ovcs->notify_state == OF_OVERLAY_POST_REMOVE) {
882 kfree(ovcs->overlay_mem);
883 kfree(ovcs->new_fdt);
891 * of_overlay_apply() - Create and apply an overlay changeset
897 * If an error is returned by an overlay changeset pre-apply notifier
898 * then no further overlay changeset pre-apply notifier will be called.
900 * If an error is returned by an overlay changeset post-apply notifier
901 * then no further overlay changeset post-apply notifier will be called.
922 ret = of_resolve_phandles(ovcs->overlay_root);
939 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
949 ret = __of_changeset_apply_notify(&ovcs->cset);
966 * of_overlay_fdt_apply() - Create and apply an overlay changeset
999 return -EBUSY;
1005 return -EINVAL;
1010 return -EINVAL;
1014 return -ENOMEM;
1020 * ovcs->notify_state must be set to OF_OVERLAY_INIT before allocating
1024 ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
1025 if (ovcs->id <= 0) {
1026 ret = ovcs->id;
1030 INIT_LIST_HEAD(&ovcs->ovcs_list);
1031 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
1032 of_changeset_init(&ovcs->cset);
1040 ret = -ENOMEM;
1043 ovcs->new_fdt = new_fdt;
1049 &ovcs->overlay_root);
1052 ret = -EINVAL;
1055 ovcs->overlay_mem = overlay_mem;
1060 * result in a memory leak if the apply partly succeeded, so do NOT
1064 *ret_ovcs_id = ovcs->id;
1111 list_for_each_entry(ce, &ovcs->cset.entries, node) {
1112 if (find_node(ce->np, remove_ce_node)) {
1114 __func__, remove_ovcs->id, ovcs->id,
1118 if (find_node(remove_ce_node, ce->np)) {
1120 __func__, remove_ovcs->id, ovcs->id,
1131 * We can safely remove the overlay only if it's the top-most one.
1144 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) {
1145 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) {
1146 pr_err("overlay #%d is not topmost\n", remove_ovcs->id);
1155 * of_overlay_remove() - Revert and free an overlay changeset
1162 * then an attempt is made to re-apply any changeset entry that was
1163 * reverted. If an error occurs on re-apply then the state of the device
1167 * A non-zero return value will not revert the changeset if error is from:
1168 * - parameter checks
1169 * - overlay changeset pre-remove notifier
1170 * - overlay changeset entry revert
1172 * If an error is returned by an overlay changeset pre-remove notifier
1173 * then no further overlay changeset pre-remove notifier will be called.
1178 * A non-zero return value will revert the changeset if error is from:
1179 * - overlay changeset entry notifier
1180 * - overlay changeset post-remove notifier
1182 * If an error is returned by an overlay changeset post-remove notifier
1183 * then no further overlay changeset post-remove notifier will be called.
1195 ret = -EBUSY;
1203 ret = -ENODEV;
1209 ret = -EBUSY;
1218 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
1225 ret = __of_changeset_revert_notify(&ovcs->cset);
1247 * overlay related memory. This is a memory leak unless a subsequent
1260 * of_overlay_remove_all() - Reverts and frees all overlay changesets
1273 ret = of_overlay_remove(&ovcs->id);