[PATCH] sparc: leon: Fix refcounting bugs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In leon_init_timers(), we should carefully handle several refcounting
bugs:

(1) we should use of_get_child_by_name() instead of of_find_node_by_name()
as the of_find_xxx API will automatically decrease the refcount of its
'from' argument.
(2) we should carefully call of_node_put() for the references returned by
OF APIs.

Fixes: 53aea7caf2e2 ("SPARC/LEON: find IRQCTRL and Timer via OF-Tree, instead of hardcoded.")
Signed-off-by: Liang He <windhl@xxxxxxx>
---
 arch/sparc/kernel/leon_kernel.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 39229940d725..917b45b2ceaf 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -305,7 +305,7 @@ static irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
 void __init leon_init_timers(void)
 {
 	int irq, eirq;
-	struct device_node *rootnp, *np, *nnp;
+	struct device_node *rootnp = NULL, *np = NULL, *nnp = NULL;
 	struct property *pp;
 	int len;
 	int icsel;
@@ -337,26 +337,35 @@ void __init leon_init_timers(void)
 		amba_system_id = *(unsigned long *)pp->value;
 
 	/* Find IRQMP IRQ Controller Registers base adr otherwise bail out */
-	np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
+	np = of_get_child_by_name(rootnp, "GAISLER_IRQMP");
 	if (!np) {
-		np = of_find_node_by_name(rootnp, "01_00d");
-		if (!np)
+		np = of_get_child_by_name(rootnp, "01_00d");
+		if (!np) {
+			of_node_put(rootnp);
 			goto bad;
+		}
 	}
 	pp = of_find_property(np, "reg", &len);
-	if (!pp)
+	of_node_put(np);
+	if (!pp) {
+		of_node_put(rootnp);
 		goto bad;
+	}
 	leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
 
 	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 	nnp = rootnp;
 
+
+
 retry:
-	np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
+	np = of_get_child_by_name(nnp, "GAISLER_GPTIMER");
 	if (!np) {
-		np = of_find_node_by_name(nnp, "01_011");
-		if (!np)
+		np = of_get_child_by_name(nnp, "01_011");
+		if (!np) {
+			of_node_put(nnp);
 			goto bad;
+		}
 	}
 
 	ampopts = 0;
@@ -366,6 +375,7 @@ void __init leon_init_timers(void)
 		if (ampopts == 0) {
 			/* Skip this instance, resource already
 			 * allocated by other OS */
+			of_node_put(nnp);
 			nnp = np;
 			goto retry;
 		}
@@ -382,6 +392,9 @@ void __init leon_init_timers(void)
 	if (pp)
 		leon3_gptimer_irq = *(unsigned int *)pp->value;
 
+	of_node_put(nnp);
+	of_node_put(np);
+
 	if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
 		goto bad;
 
-- 
2.25.1




[Index of Archives]     [Kernel Development]     [DCCP]     [Linux ARM Development]     [Linux]     [Photo]     [Yosemite Help]     [Linux ARM Kernel]     [Linux SCSI]     [Linux x86_64]     [Linux Hams]

  Powered by Linux