2022-07-08 17:05:21

by Ben Dooks

[permalink] [raw]
Subject: [PATCH] of/irq: parse interrupts-extended during irq init heirarchy calculation

When the irq controler code works out the heirarchy for initialialisation
it only looks at interrupt-parent properties, but controllers such as the
RISC-V PLIC use a extended-interrupt property and therefore do not get
properly considered during initialisation.

This means that if anything changes in the driver initialisation order
then the PLIC can get called before the CLINT nodes, and thus interrupts
do not get configured properly and the init continues without noticing
the error until drivers fail due to having no interrupts delivered.

Add code to the of_irq_init that checks for the extended-interrupt
property and adds these parent nodes so that they can be considered
during the calculations of whether an irq controller node can be
initialised.

Signed-off-by: Ben Dooks <[email protected]>
---
drivers/of/irq.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index d22f605fa7ee..abfee1fb8717 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -507,11 +507,32 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource_table);

struct of_intc_desc {
struct list_head list;
+ struct list_head parents;
of_irq_init_cb_t irq_init_cb;
struct device_node *dev;
struct device_node *interrupt_parent;
};

+static bool of_irq_init_check_parents(struct of_intc_desc *desc,
+ struct device_node *parent)
+{
+ struct of_intc_desc *search, *temp_desc;
+
+ if (list_empty(&desc->parents))
+ return desc->interrupt_parent == parent;
+
+ list_for_each_entry_safe(search, temp_desc, &desc->parents, list) {
+ if (search->interrupt_parent == parent) {
+ pr_debug("%s: %pOF removing %pOF\n",
+ __func__, desc->dev, search->interrupt_parent);
+ list_del(&search->list);
+ kfree(search);
+ }
+ }
+
+ return list_empty(&desc->parents);
+}
+
/**
* of_irq_init - Scan and init matching interrupt controllers in DT
* @matches: 0 terminated array of nodes to match and init function to call
@@ -548,6 +569,7 @@ void __init of_irq_init(const struct of_device_id *matches)
goto err;
}

+ INIT_LIST_HEAD(&desc->parents);
desc->irq_init_cb = match->data;
desc->dev = of_node_get(np);
/*
@@ -563,6 +585,40 @@ void __init of_irq_init(const struct of_device_id *matches)
desc->interrupt_parent = NULL;
}
list_add_tail(&desc->list, &intc_desc_list);
+
+ /*
+ * If the irq controller has an interrupts-extended
+ * property then go through it to find out if there
+ * are any parents in there to consider.
+ */
+ if (!desc->interrupt_parent &&
+ of_find_property(np, "interrupts-extended", NULL)) {
+ struct of_phandle_args irq;
+ int nr_irqs = of_irq_count(np);
+ int index, res;
+
+ pr_debug("%s: %pOF interrupts-extended, %d irqs\n",
+ __func__, np, nr_irqs);
+
+ for (index = 0; index < nr_irqs; index++) {
+ res = of_parse_phandle_with_args(np, "interrupts-extended",
+ "#interrupt-cells", index, &irq);
+ if (res) {
+ goto err;
+ }
+
+ pr_debug("%s: %pOF parent %pOF\n", __func__, np, irq.np);
+ if (irq.np == np)
+ continue;
+
+ temp_desc = kzalloc(sizeof(*temp_desc), GFP_KERNEL);
+ if (!temp_desc)
+ goto err;
+
+ temp_desc->interrupt_parent = irq.np;
+ list_add_tail(&temp_desc->list, &desc->parents);
+ }
+ }
}

/*
@@ -579,14 +635,14 @@ void __init of_irq_init(const struct of_device_id *matches)
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
int ret;

- if (desc->interrupt_parent != parent)
+ if (!of_irq_init_check_parents(desc, parent))
continue;

list_del(&desc->list);

of_node_set_flag(desc->dev, OF_POPULATED);

- pr_debug("of_irq_init: init %pOF (%p), parent %p\n",
+ pr_debug("of_irq_init: init %pOF (%px), parent %px\n",
desc->dev,
desc->dev, desc->interrupt_parent);
ret = desc->irq_init_cb(desc->dev,
--
2.35.1


2022-07-08 22:02:46

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH] of/irq: parse interrupts-extended during irq init heirarchy calculation

On Fri, Jul 8, 2022 at 10:52 AM Ben Dooks <[email protected]> wrote:
>
> When the irq controler code works out the heirarchy for initialialisation
> it only looks at interrupt-parent properties, but controllers such as the
> RISC-V PLIC use a extended-interrupt property and therefore do not get
> properly considered during initialisation.
>
> This means that if anything changes in the driver initialisation order
> then the PLIC can get called before the CLINT nodes, and thus interrupts
> do not get configured properly and the init continues without noticing
> the error until drivers fail due to having no interrupts delivered.
>
> Add code to the of_irq_init that checks for the extended-interrupt
> property and adds these parent nodes so that they can be considered
> during the calculations of whether an irq controller node can be
> initialised.

Isn't this already fixed by commit e91033621d56 ("of/irq: Use
interrupts-extended to find parent")?

Rob

2022-07-11 08:09:52

by Ben Dooks

[permalink] [raw]
Subject: Re: [PATCH] of/irq: parse interrupts-extended during irq init heirarchy calculation

On 08/07/2022 22:49, Rob Herring wrote:
> On Fri, Jul 8, 2022 at 10:52 AM Ben Dooks <[email protected]> wrote:
>>
>> When the irq controler code works out the heirarchy for initialialisation
>> it only looks at interrupt-parent properties, but controllers such as the
>> RISC-V PLIC use a extended-interrupt property and therefore do not get
>> properly considered during initialisation.
>>
>> This means that if anything changes in the driver initialisation order
>> then the PLIC can get called before the CLINT nodes, and thus interrupts
>> do not get configured properly and the init continues without noticing
>> the error until drivers fail due to having no interrupts delivered.
>>
>> Add code to the of_irq_init that checks for the extended-interrupt
>> property and adds these parent nodes so that they can be considered
>> during the calculations of whether an irq controller node can be
>> initialised.
>
> Isn't this already fixed by commit e91033621d56 ("of/irq: Use
> interrupts-extended to find parent")?

I didn't notice that commit, have been holding onto some of these
patches whilst sorting out permission to send.

The only thing my version does better is that it checks all of the
interrupt-extended contents so if there was a system with multiple
parents then we wouldn't consider them.

--
Ben