The of_parse_phandle() looks for the phandle in the root device tree, but as np is resolved for the target device tree, the phandle refers to the target device tree and may return a wrong node in the root tree. Therefore, we must ensure that we look for the manager-node in the target device tree and look for the manager with that name. firmwaremgr_find_by_node already uses the name for the lookup. Signed-off-by: Michael Tretter <m.tretter@xxxxxxxxxxxxxx> --- drivers/of/of_firmware.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c index 80feb3b90dba..0429875a26c4 100644 --- a/drivers/of/of_firmware.c +++ b/drivers/of/of_firmware.c @@ -9,14 +9,32 @@ static struct firmware_mgr *of_node_get_mgr(struct device_node *np) { struct device_node *mgr_node; + const __be32 *property; + phandle phandle; + int size; + /* Find fpga-mgr phandle, which may be set in a parent fpga-region. */ do { - mgr_node = of_parse_phandle(np, "fpga-mgr", 0); - if (mgr_node) - return firmwaremgr_find_by_node(mgr_node); - } while ((np = of_get_parent(np)) != NULL); - - return NULL; + property = of_get_property(np, "fpga-mgr", &size); + if (property && size == sizeof(*property)) + break; + } while ((np = of_get_parent(np)) != NULL && + of_device_is_compatible(np, "fpga-region")); + if (!property) + return NULL; + phandle = be32_to_cpup(property); + + /* + * The phandle in the np will refer to a device node in the target + * tree, which may differ from the phandle in the root tree. We need + * the name of the target node, as firmwaremgr_find_by_node performs + * the lookup by the node name. + */ + mgr_node = of_find_node_by_phandle_from(phandle, of_find_root_node(np)); + if (!mgr_node) + return NULL; + + return firmwaremgr_find_by_node(mgr_node); } struct fw_load_entry { -- 2.39.2