There are following bugs: *refcount bugs*: (1) In _init(), we need to use of_node_put() for of_find_node_by_name() and of_get_next_child(); (2) In omap_hwmod_setup_earlycon_flags(), we need to use of_node_put() for of_find_node_by_path(); (3) In omap_hwmod_fix_mpu_rt_idx(), we need to use of_node_put() for of_get_next_child(). (4) In _setup_clkctrl_provider(), we need to use of_node_get() for a new reference escaped out into 'provider->node' NOTE: (4) is a |GET| missing, not a |PUT| missing *memory leak*: (1) In _setup_clkctrl_provider(), we need to call memblock_free() in fail path. Signed-off-by: Liang He <windhl@xxxxxxx> --- v4: merge all bugs in omap_hwmon.c into one commit v3: only refcount bugs v2: merge all omap2 missing |PUT| bugs v1: fix missing |PUT| only in single file Patched file has been compiled test with multi_v7_defconfig in 5.19rc2 arch/arm/mach-omap2/omap_hwmod.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 31d1a21f6041..16f49ea4d634 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -715,7 +715,7 @@ static int __init _setup_clkctrl_provider(struct device_node *np) if (!provider) return -ENOMEM; - provider->node = np; + provider->node = of_node_get(np); provider->num_addrs = of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2; @@ -723,14 +723,21 @@ static int __init _setup_clkctrl_provider(struct device_node *np) provider->addr = memblock_alloc(sizeof(void *) * provider->num_addrs, SMP_CACHE_BYTES); - if (!provider->addr) + if (!provider->addr) { + of_node_put(np); + memblock_free(provider, sizeof(*provider)); return -ENOMEM; + } provider->size = memblock_alloc(sizeof(u32) * provider->num_addrs, SMP_CACHE_BYTES); - if (!provider->size) + if (!provider->size) { + of_node_put(np); + memblock_free(provider->addr, sizeof(void *) * provider->num_addrs); + memblock_free(provider, sizeof(*provider)); return -ENOMEM; + } for (i = 0; i < provider->num_addrs; i++) { addrp = of_get_address(np, i, &size, NULL); @@ -2179,6 +2186,7 @@ static void omap_hwmod_fix_mpu_rt_idx(struct omap_hwmod *oh, if (error) pr_err("%s: error mapping mpu_rt_idx: %i\n", __func__, error); + of_node_put(child); } /** @@ -2365,6 +2373,7 @@ static int __init _init(struct omap_hwmod *oh, void *data) r = _init_mpu_rt_base(oh, NULL, index, np); if (r < 0) { + of_node_put(bus); WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", oh->name); return 0; @@ -2372,6 +2381,7 @@ static int __init _init(struct omap_hwmod *oh, void *data) r = _init_clocks(oh, np); if (r < 0) { + of_node_put(bus); WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name); return -EINVAL; } @@ -2381,10 +2391,14 @@ static int __init _init(struct omap_hwmod *oh, void *data) parse_module_flags(oh, np); child = of_get_next_child(np, NULL); - if (child) + if (child) { parse_module_flags(oh, child); + of_node_put(child); + } } + of_node_put(bus); + oh->_state = _HWMOD_STATE_INITIALIZED; return 0; @@ -3648,6 +3662,7 @@ static void __init omap_hwmod_setup_earlycon_flags(void) np = of_find_node_by_path("/chosen"); if (np) { uart = of_get_property(np, "stdout-path", NULL); + of_node_put(np); if (uart) { np = of_find_node_by_path(uart); if (np) { @@ -3661,6 +3676,7 @@ static void __init omap_hwmod_setup_earlycon_flags(void) } if (oh) oh->flags |= DEBUG_OMAPUART_FLAGS; + of_node_put(np); } } } -- 2.25.1