]> git.itanic.dy.fi Git - linux-stable/commitdiff
powerpc/cell: Add missing of_node_put()s in cbe_regs.c
authorLiang He <windhl@126.com>
Fri, 1 Jul 2022 14:49:48 +0000 (22:49 +0800)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 5 Sep 2022 07:28:26 +0000 (17:28 +1000)
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
arch/powerpc/platforms/cell/cbe_regs.c

index 316e533afc0054808fa5d3f26ae1dfb0db52d2c5..fb4023f9ea6be6d312e0704c02b12c0c35b36442 100644 (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];