@@ -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);
}
}
}
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@126.com> --- 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(-)