Re: [PATCH 1/4] irqchip/sifive-plic: Setup cpuhp once after current handler is present

From: Marc Zyngier
Date: Sat May 16 2020 - 08:13:05 EST


Hi Anup,

On 2020-05-16 07:38, Anup Patel wrote:
For multiple PLIC instances, the plic_init() is called once for each
PLIC instance. Due to this we have two issues:
1. cpuhp_setup_state() is called multiple times
2. plic_starting_cpu() can crash for boot CPU if cpuhp_setup_state()
is called before boot CPU PLIC handler is available.

This patch fixes both above issues.

Signed-off-by: Anup Patel <anup.patel@xxxxxxx>
---
drivers/irqchip/irq-sifive-plic.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c
b/drivers/irqchip/irq-sifive-plic.c
index 822e074c0600..7dc23edb3267 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -76,6 +76,7 @@ struct plic_handler {
void __iomem *enable_base;
struct plic_priv *priv;
};
+static bool plic_cpuhp_setup_done;
static DEFINE_PER_CPU(struct plic_handler, plic_handlers);

static inline void plic_toggle(struct plic_handler *handler,
@@ -282,6 +283,7 @@ static int __init plic_init(struct device_node *node,
int error = 0, nr_contexts, nr_handlers = 0, i;
u32 nr_irqs;
struct plic_priv *priv;
+ struct plic_handler *handler;

priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -310,7 +312,6 @@ static int __init plic_init(struct device_node *node,

for (i = 0; i < nr_contexts; i++) {
struct of_phandle_args parent;
- struct plic_handler *handler;
irq_hw_number_t hwirq;
int cpu, hartid;

@@ -364,9 +365,18 @@ static int __init plic_init(struct device_node *node,
nr_handlers++;
}

- cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
+ /*
+ * We can have multiple PLIC instances so setup cpuhp state only
+ * when context handler for current/boot CPU is present.
+ */
+ handler = this_cpu_ptr(&plic_handlers);
+ if (handler->present && !plic_cpuhp_setup_done) {

If there is no context handler for the boot CPU, the system is doomed,
right? It isn't able to get any interrupt, and you don't register
the hotplug notifier that could allow secondary CPUs to boot.

So what is the point? It feels like you should just give up here.

Also, the boot CPU is always CPU 0. So checking that you only register
the hotplug notifier from CPU 0 should be enough.

+ cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
"irqchip/sifive/plic:starting",
plic_starting_cpu, plic_dying_cpu);
+ plic_cpuhp_setup_done = true;
+ }
+
pr_info("mapped %d interrupts with %d handlers for %d contexts.\n",
nr_irqs, nr_handlers, nr_contexts);
set_handle_irq(plic_handle_irq);

Thanks,

M.
--
Jazz is not dead. It just smells funny...