Commit ad4b3236 authored by Liang He's avatar Liang He Committed by Michael Ellerman
Browse files

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: default avatarLiang He <windhl@126.com>
[mpe: Drop references before pointer equality test in cbe_get_be_node()]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220701144949.252364-1-windhl@126.com
parent d9e1c610
Loading
Loading
Loading
Loading
+27 −10
Original line number Diff line number Diff line
@@ -182,10 +182,17 @@ 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];