[PATCH v1 5/9] Revert "irqchip/sifive-plic: Cleanup PLIC contexts upon irqdomain creation failure"

Emil Renner Berthing emil.renner.berthing at canonical.com
Wed Aug 14 07:56:37 PDT 2024


This reverts commit a15587277a246c388c83b1cd9cf7c1a868cd752f.

This is a prerequisite to reverting the patch converting the PLIC into a
platform driver. Unfortunately this breaks booting the Allwinner D1 SoC.

Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver")
Signed-off-by: Emil Renner Berthing <emil.renner.berthing at canonical.com>
---
 drivers/irqchip/irq-sifive-plic.c | 73 +++++++++----------------------
 1 file changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index b4c4050a02fb..85e94b8f4c06 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -423,45 +423,17 @@ static const struct of_device_id plic_match[] = {
 	{}
 };
 
-static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
-				     u32 *parent_hwirq, int *parent_cpu)
-{
-	struct device *dev = &pdev->dev;
-	struct of_phandle_args parent;
-	unsigned long hartid;
-	int rc;
-
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(dev->fwnode))
-		return -EINVAL;
-
-	rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
-	if (rc)
-		return rc;
-
-	rc = riscv_of_parent_hartid(parent.np, &hartid);
-	if (rc)
-		return rc;
-
-	*parent_hwirq = parent.args[0];
-	*parent_cpu = riscv_hartid_to_cpuid(hartid);
-	return 0;
-}
-
 static int plic_probe(struct platform_device *pdev)
 {
-	int error = 0, nr_contexts, nr_handlers = 0, cpu, i;
+	int error = 0, nr_contexts, nr_handlers = 0, i;
 	struct device *dev = &pdev->dev;
 	unsigned long plic_quirks = 0;
 	struct plic_handler *handler;
-	u32 nr_irqs, parent_hwirq;
 	struct irq_domain *domain;
 	struct plic_priv *priv;
-	irq_hw_number_t hwirq;
 	bool cpuhp_setup;
+	unsigned int cpu;
+	u32 nr_irqs;
 
 	if (is_of_node(dev->fwnode)) {
 		const struct of_device_id *id;
@@ -497,9 +469,13 @@ static int plic_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	for (i = 0; i < nr_contexts; i++) {
-		error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu);
-		if (error) {
-			dev_warn(dev, "hwirq for context%d not found\n", i);
+		struct of_phandle_args parent;
+		irq_hw_number_t hwirq;
+		int cpu;
+		unsigned long hartid;
+
+		if (of_irq_parse_one(to_of_node(dev->fwnode), i, &parent)) {
+			dev_err(dev, "failed to parse parent for context %d.\n", i);
 			continue;
 		}
 
@@ -507,7 +483,7 @@ static int plic_probe(struct platform_device *pdev)
 		 * Skip contexts other than external interrupts for our
 		 * privilege level.
 		 */
-		if (parent_hwirq != RV_IRQ_EXT) {
+		if (parent.args[0] != RV_IRQ_EXT) {
 			/* Disable S-mode enable bits if running in M-mode. */
 			if (IS_ENABLED(CONFIG_RISCV_M_MODE)) {
 				void __iomem *enable_base = priv->regs +
@@ -520,6 +496,13 @@ static int plic_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		error = riscv_of_parent_hartid(parent.np, &hartid);
+		if (error < 0) {
+			dev_warn(dev, "failed to parse hart ID for context %d.\n", i);
+			continue;
+		}
+
+		cpu = riscv_hartid_to_cpuid(hartid);
 		if (cpu < 0) {
 			dev_warn(dev, "Invalid cpuid for context %d\n", i);
 			continue;
@@ -557,7 +540,7 @@ static int plic_probe(struct platform_device *pdev)
 		handler->enable_save = devm_kcalloc(dev, DIV_ROUND_UP(nr_irqs, 32),
 						    sizeof(*handler->enable_save), GFP_KERNEL);
 		if (!handler->enable_save)
-			goto fail_cleanup_contexts;
+			return -ENOMEM;
 done:
 		for (hwirq = 1; hwirq <= nr_irqs; hwirq++) {
 			plic_toggle(handler, hwirq, 0);
@@ -570,7 +553,7 @@ static int plic_probe(struct platform_device *pdev)
 	priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
 						&plic_irqdomain_ops, priv);
 	if (WARN_ON(!priv->irqdomain))
-		goto fail_cleanup_contexts;
+		return -ENOMEM;
 
 	/*
 	 * We can have multiple PLIC instances so setup cpuhp state
@@ -598,22 +581,6 @@ static int plic_probe(struct platform_device *pdev)
 	dev_info(dev, "mapped %d interrupts with %d handlers for %d contexts.\n",
 		 nr_irqs, nr_handlers, nr_contexts);
 	return 0;
-
-fail_cleanup_contexts:
-	for (i = 0; i < nr_contexts; i++) {
-		if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu))
-			continue;
-		if (parent_hwirq != RV_IRQ_EXT || cpu < 0)
-			continue;
-
-		handler = per_cpu_ptr(&plic_handlers, cpu);
-		handler->present = false;
-		handler->hart_base = NULL;
-		handler->enable_base = NULL;
-		handler->enable_save = NULL;
-		handler->priv = NULL;
-	}
-	return -ENOMEM;
 }
 
 static struct platform_driver plic_driver = {
-- 
2.43.0




More information about the linux-riscv mailing list