lkml.org 
[lkml]   [2016]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch V2 59/67] smp: Convert core to hotplug state machine
    From: Richard Weinberger <richard@nod.at>

    Install the callbacks via the state machine. They are installed at runtime so
    smpcfd_prepare_cpu() needs to be invoked by the boot-CPU.

    Signed-off-by: Richard Weinberger <richard@nod.at>
    [ Added the dropped CPU dying case back in. ]
    Signed-off-by: Richard Cochran <rcochran@linutronix.de>
    Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
    Cc: Davidlohr Bueso <dave@stgolabs>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Mel Gorman <mgorman@techsingularity.net>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
    ---
    include/linux/cpuhotplug.h | 2 +
    include/linux/smp.h | 5 ++
    kernel/cpu.c | 9 +++++
    kernel/smp.c | 79 ++++++++++++++++++---------------------------
    4 files changed, 48 insertions(+), 47 deletions(-)

    --- a/include/linux/cpuhotplug.h
    +++ b/include/linux/cpuhotplug.h
    @@ -19,6 +19,7 @@ enum cpuhp_state {
    CPUHP_HRTIMERS_PREPARE,
    CPUHP_PROFILE_PREPARE,
    CPUHP_X2APIC_PREPARE,
    + CPUHP_SMPCFD_PREPARE,
    CPUHP_TIMERS_DEAD,
    CPUHP_NOTIFY_PREPARE,
    CPUHP_BRINGUP_CPU,
    @@ -58,6 +59,7 @@ enum cpuhp_state {
    CPUHP_AP_ARM_CORESIGHT4_STARTING,
    CPUHP_AP_ARM64_ISNDEP_STARTING,
    CPUHP_AP_LEDTRIG_STARTING,
    + CPUHP_AP_SMPCFD_DYING,
    CPUHP_AP_X86_TBOOT_DYING,
    CPUHP_AP_NOTIFY_STARTING,
    CPUHP_AP_ONLINE,
    --- a/include/linux/smp.h
    +++ b/include/linux/smp.h
    @@ -196,4 +196,9 @@ extern void arch_enable_nonboot_cpus_end

    void smp_setup_processor_id(void);

    +/* SMP core functions */
    +int smpcfd_prepare_cpu(unsigned int cpu);
    +int smpcfd_dead_cpu(unsigned int cpu);
    +int smpcfd_dying_cpu(unsigned int cpu);
    +
    #endif /* __LINUX_SMP_H */
    --- a/kernel/cpu.c
    +++ b/kernel/cpu.c
    @@ -1195,6 +1195,11 @@ static struct cpuhp_step cpuhp_bp_states
    .startup = hrtimers_prepare_cpu,
    .teardown = hrtimers_dead_cpu,
    },
    + [CPUHP_SMPCFD_PREPARE] = {
    + .name = "SMPCFD prepare",
    + .startup = smpcfd_prepare_cpu,
    + .teardown = smpcfd_dead_cpu,
    + },
    [CPUHP_TIMERS_DEAD] = {
    .name = "timers dead",
    .startup = NULL,
    @@ -1218,6 +1223,10 @@ static struct cpuhp_step cpuhp_bp_states
    .teardown = NULL,
    .cant_stop = true,
    },
    + [CPUHP_AP_SMPCFD_DYING] = {
    + .startup = NULL,
    + .teardown = smpcfd_dying_cpu,
    + },
    /*
    * Handled on controll processor until the plugged processor manages
    * this itself.
    --- a/kernel/smp.c
    +++ b/kernel/smp.c
    @@ -33,69 +33,54 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(str

    static void flush_smp_call_function_queue(bool warn_cpu_offline);

    -static int
    -hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
    +int smpcfd_prepare_cpu(unsigned int cpu)
    {
    - long cpu = (long)hcpu;
    struct call_function_data *cfd = &per_cpu(cfd_data, cpu);

    - switch (action) {
    - case CPU_UP_PREPARE:
    - case CPU_UP_PREPARE_FROZEN:
    - if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
    - cpu_to_node(cpu)))
    - return notifier_from_errno(-ENOMEM);
    - cfd->csd = alloc_percpu(struct call_single_data);
    - if (!cfd->csd) {
    - free_cpumask_var(cfd->cpumask);
    - return notifier_from_errno(-ENOMEM);
    - }
    - break;
    -
    -#ifdef CONFIG_HOTPLUG_CPU
    - case CPU_UP_CANCELED:
    - case CPU_UP_CANCELED_FROZEN:
    - /* Fall-through to the CPU_DEAD[_FROZEN] case. */
    -
    - case CPU_DEAD:
    - case CPU_DEAD_FROZEN:
    + if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
    + cpu_to_node(cpu)))
    + return -ENOMEM;
    + cfd->csd = alloc_percpu(struct call_single_data);
    + if (!cfd->csd) {
    free_cpumask_var(cfd->cpumask);
    - free_percpu(cfd->csd);
    - break;
    + return -ENOMEM;
    + }

    - case CPU_DYING:
    - case CPU_DYING_FROZEN:
    - /*
    - * The IPIs for the smp-call-function callbacks queued by other
    - * CPUs might arrive late, either due to hardware latencies or
    - * because this CPU disabled interrupts (inside stop-machine)
    - * before the IPIs were sent. So flush out any pending callbacks
    - * explicitly (without waiting for the IPIs to arrive), to
    - * ensure that the outgoing CPU doesn't go offline with work
    - * still pending.
    - */
    - flush_smp_call_function_queue(false);
    - break;
    -#endif
    - };
    + return 0;
    +}

    - return NOTIFY_OK;
    +int smpcfd_dead_cpu(unsigned int cpu)
    +{
    + struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
    +
    + free_cpumask_var(cfd->cpumask);
    + free_percpu(cfd->csd);
    + return 0;
    }

    -static struct notifier_block hotplug_cfd_notifier = {
    - .notifier_call = hotplug_cfd,
    -};
    +int smpcfd_dying_cpu(unsigned int cpu)
    +{
    + /*
    + * The IPIs for the smp-call-function callbacks queued by other
    + * CPUs might arrive late, either due to hardware latencies or
    + * because this CPU disabled interrupts (inside stop-machine)
    + * before the IPIs were sent. So flush out any pending callbacks
    + * explicitly (without waiting for the IPIs to arrive), to
    + * ensure that the outgoing CPU doesn't go offline with work
    + * still pending.
    + */
    + flush_smp_call_function_queue(false);
    + return 0;
    +}

    void __init call_function_init(void)
    {
    - void *cpu = (void *)(long)smp_processor_id();
    int i;

    for_each_possible_cpu(i)
    init_llist_head(&per_cpu(call_single_queue, i));

    - hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
    - register_cpu_notifier(&hotplug_cfd_notifier);
    + smpcfd_prepare_cpu(smp_processor_id());
    }

    /*

    \
     
     \ /
      Last update: 2016-07-13 20:01    [W:4.165 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site