[PATCH v6 04/10] of/overlay: look up absolute target-paths absolutely
Abdurrahman Hussain <[email protected]>
| Newsgroups | gmane.linux.drivers.devicetree,gmane.linux.kernel |
|---|---|
| Message-ID | <[email protected]> |
find_target() with a non-NULL target base concatenates the base path and the fragment's target-path via "%pOF%s": target-path="/foo" resolves to "<base>/foo" and can never reach the DT root. An overlay applied with a base cannot both extend the base subtree and add /aliases entries, which is what a PCI device declaring its peripherals under dev_of_node() needs for alias-based bus numbering. Treat any non-empty target-path as absolute. An empty target-path still means the base itself, the only form used by the one in-tree caller passing a base (drivers/misc/lan966x_pci.c). Spell the contract out in the kernel-doc for @base/@target_base and in find_target()'s strategy comment. Assisted-by: Claude:claude-fable-5 [Claude Code] Signed-off-by: Abdurrahman Hussain <[email protected]> --- drivers/of/overlay.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 08d5351746be..74aea704835a 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -688,12 +688,15 @@ static int build_changeset(struct overlay_changeset *ovcs) * * 1) "target" property containing the phandle of the target * 2) "target-path" property containing the path of the target + * + * With a non-NULL @target_base, an empty "target-path" means + * @target_base itself; any non-empty "target-path" is resolved + * absolutely from the live-tree root. */ static struct device_node *find_target(const struct device_node *info_node, const struct device_node *target_base) { struct device_node *node; - char *target_path; const char *path; u32 val; int ret; @@ -709,23 +712,14 @@ static struct device_node *find_target(const struct device_node *info_node, ret = of_property_read_string(info_node, "target-path", &path); if (!ret) { - if (target_base) { - target_path = kasprintf(GFP_KERNEL, "%pOF%s", target_base, path); - if (!target_path) - return NULL; - node = of_find_node_by_path(target_path); - if (!node) { - pr_err("find target, node: %pOF, path '%s' not found\n", - info_node, target_path); - } - kfree(target_path); - } else { - node = of_find_node_by_path(path); - if (!node) { - pr_err("find target, node: %pOF, path '%s' not found\n", - info_node, path); - } - } + /* an empty target-path means the target base itself */ + if (target_base && path[0] == '\0') + return of_node_get((struct device_node *)target_base); + + node = of_find_node_by_path(path); + if (!node) + pr_err("find target, node: %pOF, path '%s' not found\n", + info_node, path); return node; } @@ -737,7 +731,9 @@ static struct device_node *find_target(const struct device_node *info_node, /** * init_overlay_changeset() - initialize overlay changeset from overlay tree * @ovcs: Overlay changeset to build - * @target_base: Point to the target node to apply overlay + * @target_base: Target for fragments with an empty "target-path"; + * fragments with a non-empty "target-path" resolve + * absolutely and ignore @target_base * * Initialize @ovcs. Populate @ovcs->fragments with node information from * the top level of @overlay_root. The relevant top level nodes are the @@ -982,7 +978,9 @@ static int of_overlay_apply(struct overlay_changeset *ovcs, * @overlay_fdt: pointer to overlay FDT * @overlay_fdt_size: number of bytes in @overlay_fdt * @ret_ovcs_id: pointer for returning created changeset id - * @base: pointer for the target node to apply overlay + * @base: target for fragments with an empty "target-path"; + * fragments with a non-empty "target-path" resolve + * absolutely and ignore @base * * Creates and applies an overlay changeset. * -- 2.54.0