From: Ben Dooks <ben.dooks@sifive.com>
To: devicetree@vger.kernel.org, frowand.list@gmail.com
Cc: linux-kernel@vger.kernel.org, robh+dt@kernel.org,
Sudip Mukherjee <sudip.mukherjee@sifive.com>,
Jude Onyenegecha <jude.onyenegecha@sifive.com>,
Ben Dooks <ben.dooks@sifive.com>
Subject: [PATCH] of/irq: parse interrupts-extended during irq init heirarchy calculation
Date: Fri, 8 Jul 2022 17:52:25 +0100 [thread overview]
Message-ID: <20220708165225.269192-1-ben.dooks@sifive.com> (raw)
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 <ben.dooks@sifive.com>
---
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
next reply other threads:[~2022-07-08 16:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-08 16:52 Ben Dooks [this message]
2022-07-08 21:49 ` Rob Herring
2022-07-11 7:16 ` Ben Dooks
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220708165225.269192-1-ben.dooks@sifive.com \
--to=ben.dooks@sifive.com \
--cc=devicetree@vger.kernel.org \
--cc=frowand.list@gmail.com \
--cc=jude.onyenegecha@sifive.com \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.org \
--cc=sudip.mukherjee@sifive.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®