@@ -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;
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@126.com> --- arch/sparc/kernel/leon_kernel.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)