Message ID | 20220325143833.402631-12-deller@gmx.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [01/12] parisc: Switch from GENERIC_CPU_DEVICES to GENERIC_ARCH_TOPOLOGY | expand |
Am Freitag, 25. März 2022, 15:38:33 CET schrieb Helge Deller: > Add relevant code to __cpu_die() and __cpu_disable() to finally enable > the CPU hotplugging features. Reset the irq count values in smp_callin() > to zero before bringing up the CPU. > > Use "chcpu -d 1" to bring CPU1 down, and "chcpu -e 1" to bring it up. > > Signed-off-by: Helge Deller <deller@gmx.de> > --- > arch/parisc/Kconfig | 1 + > arch/parisc/include/asm/smp.h | 9 +--- > arch/parisc/kernel/smp.c | 80 +++++++++++++++++++++++++++++++++-- > 3 files changed, 79 insertions(+), 11 deletions(-) > > diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c > index a32a882a2d58..60cc33fd345c 100644 > --- a/arch/parisc/kernel/smp.c > +++ b/arch/parisc/kernel/smp.c > @@ -430,10 +444,68 @@ void smp_cpus_done(unsigned int cpu_max) > > int __cpu_up(unsigned int cpu, struct task_struct *tidle) > { > - if (cpu != 0 && cpu < parisc_max_cpus && smp_boot_one_cpu(cpu, tidle)) > - return -ENOSYS; > + if (cpu_online(cpu)) > + return 0; > + > + if (num_online_cpus() < parisc_max_cpus && smp_boot_one_cpu(cpu, tidle)) > + return -EIO; I had to look up parisc_max_cpus, and found this: > static int parisc_max_cpus = 1; Hm, signed? > parisc_max_cpus = max_cpus; > if (!max_cpus) > printk(KERN_INFO "SMP mode deactivated.\n"); So parisc_max_cpus is now 0, which seems wrong. Shouldn't the check be before the assignment? This would have avoided the "cpu != 0" in the old code completely. > + > + return cpu_online(cpu) ? 0 : -EIO; > +} > + > +/* > + * __cpu_disable runs on the processor to be shutdown. > + */ > +int __cpu_disable(void) > +{ > +#ifdef CONFIG_HOTPLUG_CPU > + unsigned int cpu = smp_processor_id(); > + > + remove_cpu_topology(cpu); > + > + /* > + * Take this CPU offline. Once we clear this, we can't return, > + * and we must not schedule until we're ready to give up the cpu. > + */ > + set_cpu_online(cpu, false); > + > + /* > + * disable IPI interrupt > + */ > + disable_percpu_irq(IPI_IRQ); > + > + /* > + * migrate IRQs away from this CPU > + */ > + irq_migrate_all_off_this_cpu(); While I really enjoy good code comments the last 2 seem a t bit wasteful, given that the code is basically exactly the same as the text. > + /* > + * Flush user cache and TLB mappings, and then remove this CPU > + * from the vm mask set of all processes. > + * > + * Caches are flushed to the Level of Unification Inner Shareable > + * to write-back dirty lines to unified caches shared by all CPUs. > + */ > + flush_cache_all_local(); > + flush_tlb_all_local(NULL); > > - return cpu_online(cpu) ? 0 : -ENOSYS; > + /* disable all irqs, including timer irq */ > + local_irq_disable(); > +#endif > + return 0; > +} > + > +/* > + * called on the thread which is asking for a CPU to be shutdown - > + * waits until shutdown has completed, or it is timed out. > + */ > +void __cpu_die(unsigned int cpu) > +{ > + if (!cpu_wait_death(cpu, 5)) { > + pr_crit("CPU%u: cpu didn't die\n", cpu); > + return; > + } > + pr_debug("CPU%u: shutdown\n", cpu); > } > > #ifdef CONFIG_PROC_FS > -- > 2.35.1
On 3/25/22 18:10, Rolf Eike Beer wrote: > Am Freitag, 25. März 2022, 15:38:33 CET schrieb Helge Deller: >> Add relevant code to __cpu_die() and __cpu_disable() to finally enable >> the CPU hotplugging features. Reset the irq count values in smp_callin() >> to zero before bringing up the CPU. >> >> Use "chcpu -d 1" to bring CPU1 down, and "chcpu -e 1" to bring it up. >> >> Signed-off-by: Helge Deller <deller@gmx.de> >> --- >> arch/parisc/Kconfig | 1 + >> arch/parisc/include/asm/smp.h | 9 +--- >> arch/parisc/kernel/smp.c | 80 +++++++++++++++++++++++++++++++++-- >> 3 files changed, 79 insertions(+), 11 deletions(-) >> >> diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c >> index a32a882a2d58..60cc33fd345c 100644 >> --- a/arch/parisc/kernel/smp.c >> +++ b/arch/parisc/kernel/smp.c >> @@ -430,10 +444,68 @@ void smp_cpus_done(unsigned int cpu_max) >> >> int __cpu_up(unsigned int cpu, struct task_struct *tidle) >> { >> - if (cpu != 0 && cpu < parisc_max_cpus && smp_boot_one_cpu(cpu, > tidle)) >> - return -ENOSYS; >> + if (cpu_online(cpu)) >> + return 0; >> + >> + if (num_online_cpus() < parisc_max_cpus && smp_boot_one_cpu(cpu, > tidle)) >> + return -EIO; > > I had to look up parisc_max_cpus, and found this: > >> static int parisc_max_cpus = 1; > > Hm, signed? > >> parisc_max_cpus = max_cpus; >> if (!max_cpus) >> printk(KERN_INFO "SMP mode deactivated.\n"); > > So parisc_max_cpus is now 0, which seems wrong. Shouldn't the check be before > the assignment? This would have avoided the "cpu != 0" in the old code > completely. No, the old cpu != 0 && ....smp_boot_one_cpu(cpu, tidle)) was to avoid that smp_boot_one_cpu() gets called for the monarch cpu. Anyway, you are right, the code could need cleanups. But in my patch series I wanted to keep the changes minimal in the first place. > >> + >> + return cpu_online(cpu) ? 0 : -EIO; >> +} >> + >> +/* >> + * __cpu_disable runs on the processor to be shutdown. >> + */ >> +int __cpu_disable(void) >> +{ >> +#ifdef CONFIG_HOTPLUG_CPU >> + unsigned int cpu = smp_processor_id(); >> + >> + remove_cpu_topology(cpu); >> + >> + /* >> + * Take this CPU offline. Once we clear this, we can't return, >> + * and we must not schedule until we're ready to give up the cpu. >> + */ >> + set_cpu_online(cpu, false); >> + >> + /* >> + * disable IPI interrupt >> + */ >> + disable_percpu_irq(IPI_IRQ); >> + >> + /* >> + * migrate IRQs away from this CPU >> + */ >> + irq_migrate_all_off_this_cpu(); > > While I really enjoy good code comments the last 2 seem a t bit wasteful, > given that the code is basically exactly the same as the text. Yep. Helge
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 6bd42c82a019..ec5bb9626d06 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -56,6 +56,7 @@ config PARISC select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_API select GENERIC_SCHED_CLOCK + select GENERIC_IRQ_MIGRATION select HAVE_UNSTABLE_SCHED_CLOCK if SMP select LEGACY_TIMER_TICK select CPU_NO_EFFICIENT_FFS diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h index 2279ebe5e2da..94d1f21ce99a 100644 --- a/arch/parisc/include/asm/smp.h +++ b/arch/parisc/include/asm/smp.h @@ -44,12 +44,7 @@ static inline void smp_send_all_nop(void) { return; } #define NO_PROC_ID 0xFF /* No processor magic marker */ #define ANY_PROC_ID 0xFF /* Any processor magic marker */ -static inline int __cpu_disable (void) { - return 0; -} -static inline void __cpu_die (unsigned int cpu) { - while(1) - ; -} +int __cpu_disable(void); +void __cpu_die(unsigned int cpu); #endif /* __ASM_SMP_H */ diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index a32a882a2d58..60cc33fd345c 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -30,6 +30,7 @@ #include <linux/ftrace.h> #include <linux/cpu.h> #include <linux/kgdb.h> +#include <linux/sched/hotplug.h> #include <linux/atomic.h> #include <asm/current.h> @@ -309,7 +310,7 @@ smp_cpu_init(int cpunum) * Slaves start using C here. Indirectly called from smp_slave_stext. * Do what start_kernel() and main() do for boot strap processor (aka monarch) */ -void __init smp_callin(unsigned long pdce_proc) +void __cpuinit smp_callin(unsigned long pdce_proc) { int slave_id = cpu_now_booting; @@ -339,6 +340,19 @@ int smp_boot_one_cpu(int cpuid, struct task_struct *idle) const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); long timeout; +#ifdef CONFIG_HOTPLUG_CPU + int i; + + /* reset irq statistics for this CPU */ + memset(&per_cpu(irq_stat, cpuid), 0, sizeof(irq_cpustat_t)); + for (i = 0; i < NR_IRQS; i++) { + struct irq_desc *desc = irq_to_desc(i); + + if (desc && desc->kstat_irqs) + *per_cpu_ptr(desc->kstat_irqs, cpuid) = 0; + } +#endif + /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) */ @@ -430,10 +444,68 @@ void smp_cpus_done(unsigned int cpu_max) int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - if (cpu != 0 && cpu < parisc_max_cpus && smp_boot_one_cpu(cpu, tidle)) - return -ENOSYS; + if (cpu_online(cpu)) + return 0; + + if (num_online_cpus() < parisc_max_cpus && smp_boot_one_cpu(cpu, tidle)) + return -EIO; + + return cpu_online(cpu) ? 0 : -EIO; +} + +/* + * __cpu_disable runs on the processor to be shutdown. + */ +int __cpu_disable(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + unsigned int cpu = smp_processor_id(); + + remove_cpu_topology(cpu); + + /* + * Take this CPU offline. Once we clear this, we can't return, + * and we must not schedule until we're ready to give up the cpu. + */ + set_cpu_online(cpu, false); + + /* + * disable IPI interrupt + */ + disable_percpu_irq(IPI_IRQ); + + /* + * migrate IRQs away from this CPU + */ + irq_migrate_all_off_this_cpu(); + + /* + * Flush user cache and TLB mappings, and then remove this CPU + * from the vm mask set of all processes. + * + * Caches are flushed to the Level of Unification Inner Shareable + * to write-back dirty lines to unified caches shared by all CPUs. + */ + flush_cache_all_local(); + flush_tlb_all_local(NULL); - return cpu_online(cpu) ? 0 : -ENOSYS; + /* disable all irqs, including timer irq */ + local_irq_disable(); +#endif + return 0; +} + +/* + * called on the thread which is asking for a CPU to be shutdown - + * waits until shutdown has completed, or it is timed out. + */ +void __cpu_die(unsigned int cpu) +{ + if (!cpu_wait_death(cpu, 5)) { + pr_crit("CPU%u: cpu didn't die\n", cpu); + return; + } + pr_debug("CPU%u: shutdown\n", cpu); } #ifdef CONFIG_PROC_FS
Add relevant code to __cpu_die() and __cpu_disable() to finally enable the CPU hotplugging features. Reset the irq count values in smp_callin() to zero before bringing up the CPU. Use "chcpu -d 1" to bring CPU1 down, and "chcpu -e 1" to bring it up. Signed-off-by: Helge Deller <deller@gmx.de> --- arch/parisc/Kconfig | 1 + arch/parisc/include/asm/smp.h | 9 +--- arch/parisc/kernel/smp.c | 80 +++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 11 deletions(-) -- 2.35.1