Re: [PATCH v1] irqchip/gic-v3-its: Drop ITS node reference on its_of_probe() errors
From: Marc Zyngier
Date: Thu Sep 24 2026 - 16:13:18 EST
On Wed, 23 Sep 2026 18:10:26 +0100,
Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx> wrote:
>
> On Wed, 23 Sep 2026 12:54:40 -0400
> Yuho Choi <oss.patchbox@xxxxxxxxx> wrote:
>
> > its_of_probe() walks the ITS nodes with of_find_matching_node(), which
> > drops the reference on the previous node and returns the next one with
> > its reference count raised. The loops are balanced when they run to the
> > end, but the three error returns (a failed its_reset_one(), a failed
> > its_node_init() and a failed its_probe_one()) leave with the current
> > node still referenced.
> >
> > Drop it before returning.
> >
> > Fixes: c733ebb7cb67 ("irqchip/gic-v3-its: Reset each ITS's BASERn register before probe")
> > Fixes: 9585a495ac93 ("irqchip/gic-v3-its: Split allocation from initialisation of its_node")
> > Signed-off-by: Yuho Choi <oss.patchbox@xxxxxxxxx>
>
> I only took a very quick look but why can't this use for_each_matching_node()
>
> That doesn't solve your problem but it would be easy to add a for_each_matching_node_scoped()
> in similar spirit to for_each_child_of_node_scoped() I think and that would give you a cleaner fix here.
+1. It'd be much better to have an infrastructure for this sort of
things.
Otherwise, the obvious way to do this locally would be as below,
instead of the proposed sprinkling of direct of_node_put(). Completely
untested, as usual.
M.
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e9807af235373..91e08b5229b1c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -5561,7 +5561,6 @@ static void its_node_destroy(struct its_node *its)
static int __init its_of_probe(struct device_node *node)
{
- struct device_node *np;
struct resource res;
int err;
@@ -5571,7 +5570,7 @@ static int __init its_of_probe(struct device_node *node)
* reset, don't even try to go any further, as this could
* result in something even worse.
*/
- for (np = of_find_matching_node(node, its_device_id); np;
+ for (struct device_node *np __free(device_node) = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
if (!of_device_is_available(np) ||
!of_property_read_bool(np, "msi-controller") ||
@@ -5583,7 +5582,7 @@ static int __init its_of_probe(struct device_node *node)
return err;
}
- for (np = of_find_matching_node(node, its_device_id); np;
+ for (struct device_node *np __free(device_node) = of_find_matching_node(node, its_device_id); np;
np = of_find_matching_node(np, its_device_id)) {
struct its_node *its;
--
Without deviation from the norm, progress is not possible.