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
This commit is contained in:
Liang He 2022-07-01 22:49:48 +08:00 committed by Michael Ellerman
parent d9e1c6104d
commit ad4b323693
1 changed files with 27 additions and 10 deletions

View File

@ -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];