lkml.org 
[lkml]   [2020]   [Jun]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 296/376] irqchip/sifive-plic: Setup cpuhp once after boot CPU handler is present
    Date
    From: Anup Patel <anup.patel@wdc.com>

    commit 2234ae846ccb9ebdf4c391824cb79e73674dceda upstream.

    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.

    Address both issues by only initializing the HP notifiers when
    the boot CPU setup is complete.

    Fixes: f1ad1133b18f ("irqchip/sifive-plic: Add support for multiple PLICs")
    Signed-off-by: Anup Patel <anup.patel@wdc.com>
    Signed-off-by: Marc Zyngier <maz@kernel.org>
    Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
    Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
    Cc: stable@vger.kernel.org
    Link: https://lore.kernel.org/r/20200518091441.94843-3-anup.patel@wdc.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/irqchip/irq-sifive-plic.c | 14 ++++++++++++--
    1 file changed, 12 insertions(+), 2 deletions(-)

    --- 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,
    @@ -285,6 +286,7 @@ static int __init plic_init(struct devic
    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)
    @@ -315,7 +317,6 @@ static int __init plic_init(struct devic

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

    @@ -369,9 +370,18 @@ done:
    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) {
    + 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);

    \
     
     \ /
      Last update: 2020-06-19 17:32    [W:4.017 / U:0.264 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site