On Tue, Jun 18, 2024 at 7:00 PM Emil Renner Berthing <emil.renner.berthing@xxxxxxxxxxxxx> wrote: > > Anup Patel wrote: > > The PLIC driver does not require very early initialization so convert > > it into a platform driver. > > > > After conversion, the PLIC driver is probed after CPUs are brought-up > > so setup cpuhp state after context handler of all online CPUs are > > initialized otherwise PLIC driver crashes for platforms with multiple > > PLIC instances. > > > > Signed-off-by: Anup Patel <apatel@xxxxxxxxxxxxxxxx> > > Hi Anup, > > Sorry for the late reply to the mailing list, but ever since 6.9 where this was > applied my Allwinner D1 based boards no longer boot. This is the log of my > LicheeRV Dock booting plain 6.10-rc4, locking up and then rebooting due to the > the watchdog timing out: > > https://pastebin.com/raw/nsbzgEKW > > On 6.10-rc4 I can bring the same board to boot by reverting this patch and all > patches building on it. Eg.: > > git revert e306a894bd51 a7fb69ffd7ce abb720579490 \ > 956521064780 a15587277a24 6c725f33d67b \ > b68d0ff529a9 25d862e183d4 8ec99b033147 Does your board boot with only SBI timer driver enabled ? If yes then probing of Allwinner timer driver needs to be fixed since it depends on PLIC. Regards, Anup > > After that it boots but run into this separate issue: > https://lore.kernel.org/all/DM6PR01MB58047C810DDD5D0AE397CADFF7C22@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ > > Samuel: After the reverts above applying this also prevents my board from > booting: > https://lore.kernel.org/all/20240312192519.1602493-1-samuel.holland@xxxxxxxxxx/ > > /Emil > > > --- > > drivers/irqchip/irq-sifive-plic.c | 101 ++++++++++++++++++------------ > > 1 file changed, 61 insertions(+), 40 deletions(-) > > > > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c > > index 5b7bc4fd9517..7400a07fc479 100644 > > --- a/drivers/irqchip/irq-sifive-plic.c > > +++ b/drivers/irqchip/irq-sifive-plic.c > > @@ -64,6 +64,7 @@ > > #define PLIC_QUIRK_EDGE_INTERRUPT 0 > > > > struct plic_priv { > > + struct device *dev; > > struct cpumask lmask; > > struct irq_domain *irqdomain; > > void __iomem *regs; > > @@ -406,30 +407,50 @@ static int plic_starting_cpu(unsigned int cpu) > > return 0; > > } > > > > -static int __init __plic_init(struct device_node *node, > > - struct device_node *parent, > > - unsigned long plic_quirks) > > +static const struct of_device_id plic_match[] = { > > + { .compatible = "sifive,plic-1.0.0" }, > > + { .compatible = "riscv,plic0" }, > > + { .compatible = "andestech,nceplic100", > > + .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) }, > > + { .compatible = "thead,c900-plic", > > + .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) }, > > + {} > > +}; > > + > > +static int plic_probe(struct platform_device *pdev) > > { > > int error = 0, nr_contexts, nr_handlers = 0, i; > > - u32 nr_irqs; > > - struct plic_priv *priv; > > + struct device *dev = &pdev->dev; > > + unsigned long plic_quirks = 0; > > struct plic_handler *handler; > > + struct plic_priv *priv; > > + bool cpuhp_setup; > > unsigned int cpu; > > + u32 nr_irqs; > > + > > + if (is_of_node(dev->fwnode)) { > > + const struct of_device_id *id; > > + > > + id = of_match_node(plic_match, to_of_node(dev->fwnode)); > > + if (id) > > + plic_quirks = (unsigned long)id->data; > > + } > > > > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > > if (!priv) > > return -ENOMEM; > > > > + priv->dev = dev; > > priv->plic_quirks = plic_quirks; > > > > - priv->regs = of_iomap(node, 0); > > + priv->regs = of_iomap(to_of_node(dev->fwnode), 0); > > if (WARN_ON(!priv->regs)) { > > error = -EIO; > > goto out_free_priv; > > } > > > > error = -EINVAL; > > - of_property_read_u32(node, "riscv,ndev", &nr_irqs); > > + of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", &nr_irqs); > > if (WARN_ON(!nr_irqs)) > > goto out_iounmap; > > > > @@ -439,13 +460,13 @@ static int __init __plic_init(struct device_node *node, > > if (!priv->prio_save) > > goto out_free_priority_reg; > > > > - nr_contexts = of_irq_count(node); > > + nr_contexts = of_irq_count(to_of_node(dev->fwnode)); > > if (WARN_ON(!nr_contexts)) > > goto out_free_priority_reg; > > > > error = -ENOMEM; > > - priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, > > - &plic_irqdomain_ops, priv); > > + priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1, > > + &plic_irqdomain_ops, priv); > > if (WARN_ON(!priv->irqdomain)) > > goto out_free_priority_reg; > > > > @@ -455,7 +476,7 @@ static int __init __plic_init(struct device_node *node, > > int cpu; > > unsigned long hartid; > > > > - if (of_irq_parse_one(node, i, &parent)) { > > + if (of_irq_parse_one(to_of_node(dev->fwnode), i, &parent)) { > > pr_err("failed to parse parent for context %d.\n", i); > > continue; > > } > > @@ -491,7 +512,7 @@ static int __init __plic_init(struct device_node *node, > > > > /* Find parent domain and register chained handler */ > > if (!plic_parent_irq && irq_find_host(parent.np)) { > > - plic_parent_irq = irq_of_parse_and_map(node, i); > > + plic_parent_irq = irq_of_parse_and_map(to_of_node(dev->fwnode), i); > > if (plic_parent_irq) > > irq_set_chained_handler(plic_parent_irq, > > plic_handle_irq); > > @@ -533,20 +554,29 @@ static int __init __plic_init(struct device_node *node, > > > > /* > > * We can have multiple PLIC instances so setup cpuhp state > > - * and register syscore operations only when context handler > > - * for current/boot CPU is present. > > + * and register syscore operations only once after context > > + * handlers of all online CPUs are initialized. > > */ > > - handler = this_cpu_ptr(&plic_handlers); > > - if (handler->present && !plic_cpuhp_setup_done) { > > - cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, > > - "irqchip/sifive/plic:starting", > > - plic_starting_cpu, plic_dying_cpu); > > - register_syscore_ops(&plic_irq_syscore_ops); > > - plic_cpuhp_setup_done = true; > > + if (!plic_cpuhp_setup_done) { > > + cpuhp_setup = true; > > + for_each_online_cpu(cpu) { > > + handler = per_cpu_ptr(&plic_handlers, cpu); > > + if (!handler->present) { > > + cpuhp_setup = false; > > + break; > > + } > > + } > > + if (cpuhp_setup) { > > + cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, > > + "irqchip/sifive/plic:starting", > > + plic_starting_cpu, plic_dying_cpu); > > + register_syscore_ops(&plic_irq_syscore_ops); > > + plic_cpuhp_setup_done = true; > > + } > > } > > > > - pr_info("%pOFP: mapped %d interrupts with %d handlers for" > > - " %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts); > > + pr_info("%pOFP: mapped %d interrupts with %d handlers for %d contexts.\n", > > + to_of_node(dev->fwnode), nr_irqs, nr_handlers, nr_contexts); > > return 0; > > > > out_free_enable_reg: > > @@ -563,20 +593,11 @@ static int __init __plic_init(struct device_node *node, > > return error; > > } > > > > -static int __init plic_init(struct device_node *node, > > - struct device_node *parent) > > -{ > > - return __plic_init(node, parent, 0); > > -} > > - > > -IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init); > > -IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */ > > - > > -static int __init plic_edge_init(struct device_node *node, > > - struct device_node *parent) > > -{ > > - return __plic_init(node, parent, BIT(PLIC_QUIRK_EDGE_INTERRUPT)); > > -} > > - > > -IRQCHIP_DECLARE(andestech_nceplic100, "andestech,nceplic100", plic_edge_init); > > -IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init); > > +static struct platform_driver plic_driver = { > > + .driver = { > > + .name = "riscv-plic", > > + .of_match_table = plic_match, > > + }, > > + .probe = plic_probe, > > +}; > > +builtin_platform_driver(plic_driver); > > -- > > 2.34.1 > > > > > > _______________________________________________ > > linux-riscv mailing list > > linux-riscv@xxxxxxxxxxxxxxxxxxx > > http://lists.infradead.org/mailman/listinfo/linux-riscv