diff options
author | Liang He <windhl@126.com> | 2022-07-01 22:49:48 +0800 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2022-09-05 17:28:26 +1000 |
commit | ad4b323693abd221798a6479105d22c79605aa0f (patch) | |
tree | e71e4b48ee87810281f983c6831740ce62b06915 /arch/powerpc | |
parent | d9e1c6104d87d4027133b28f5ccab8f999830acd (diff) |
powerpc/cell: Add missing of_node_put()s in cbe_regs.c
There are several bugs as following:
(1) In cbe_get_be_node(), hold the reference returned by of_find_xxx and
of_get_xxx OF APIs and use it to call of_node_put().
(2) In cbe_fill_regs_map(), same as above.
(3) In cbe_regs_init(), during the iteration of for_each_node_by_type(),
the refcount of 'cpu' will be automatically increased and decreased.
However, there is a reference escaped out into 'map->cpu_node' and
it should be properly handled.
Signed-off-by: Liang He <windhl@126.com>
[mpe: Drop references before pointer equality test in cbe_get_be_node()]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220701144949.252364-1-windhl@126.com
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_regs.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 316e533afc00..fb4023f9ea6b 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -182,9 +182,16 @@ static struct device_node *__init cbe_get_be_node(int cpu_id) if (WARN_ON_ONCE(!cpu_handle)) return np; - for (i=0; i<len; i++) - if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) + for (i = 0; i < len; i++) { + struct device_node *ch_np = of_find_node_by_phandle(cpu_handle[i]); + struct device_node *ci_np = of_get_cpu_node(cpu_id, NULL); + + of_node_put(ch_np); + of_node_put(ci_np); + + if (ch_np == ci_np) return np; + } } return NULL; @@ -193,21 +200,30 @@ static struct device_node *__init cbe_get_be_node(int cpu_id) static void __init cbe_fill_regs_map(struct cbe_regs_map *map) { if(map->be_node) { - struct device_node *be, *np; + struct device_node *be, *np, *parent_np; be = map->be_node; - for_each_node_by_type(np, "pervasive") - if (of_get_parent(np) == be) + for_each_node_by_type(np, "pervasive") { + parent_np = of_get_parent(np); + if (parent_np == be) map->pmd_regs = of_iomap(np, 0); + of_node_put(parent_np); + } - for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") - if (of_get_parent(np) == be) + for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") { + parent_np = of_get_parent(np); + if (parent_np == be) map->iic_regs = of_iomap(np, 2); + of_node_put(parent_np); + } - for_each_node_by_type(np, "mic-tm") - if (of_get_parent(np) == be) + for_each_node_by_type(np, "mic-tm") { + parent_np = of_get_parent(np); + if (parent_np == be) map->mic_tm_regs = of_iomap(np, 0); + of_node_put(parent_np); + } } else { struct device_node *cpu; /* That hack must die die die ! */ @@ -261,7 +277,8 @@ void __init cbe_regs_init(void) of_node_put(cpu); return; } - map->cpu_node = cpu; + of_node_put(map->cpu_node); + map->cpu_node = of_node_get(cpu); for_each_possible_cpu(i) { struct cbe_thread_map *thread = &cbe_thread_map[i]; |