From abcee5fb0dfbb248d883a2f6bdb4820abe3ac524 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 8 Sep 2011 09:06:10 +0100 Subject: ARM: SoC: add per-platform SMP operations This adds a 'struct smp_operations' to abstract the CPU initialization and hot plugging functions on SMP systems, which otherwise conflict in a multiplatform kernel. This also helps shmobile and potentially others that have more than one method to do these. To allow the kernel to continue building, the platform hooks are defined as weak symbols which are overrided by the platform code. Once all platforms are converted, the "weak" attribute will be removed and the function made static. Unlike the original version from Marc, this new version from Arnd does not use a generalized abstraction for per-soc data structures but only tries to solve the problem for the SMP operations. This way, we can collapse the previous four data structures into a single struct, which is less systematic but also easier to follow as a causal reader. Signed-off-by: Marc Zyngier Acked-by: Nicolas Pitre Signed-off-by: Arnd Bergmann --- arch/arm/include/asm/smp.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'arch/arm/include/asm/smp.h') diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index ae29293270a3..f79a9f51e322 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -93,4 +93,37 @@ extern void platform_cpu_enable(unsigned int cpu); extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); +struct smp_operations { +#ifdef CONFIG_SMP + /* + * Setup the set of possible CPUs (via set_cpu_possible) + */ + void (*smp_init_cpus)(void); + /* + * Initialize cpu_possible map, and enable coherency + */ + void (*smp_prepare_cpus)(unsigned int max_cpus); + + /* + * Perform platform specific initialisation of the specified CPU. + */ + void (*smp_secondary_init)(unsigned int cpu); + /* + * Boot a secondary CPU, and assign it the specified idle task. + * This also gives us the initial stack to use for this CPU. + */ + int (*smp_boot_secondary)(unsigned int cpu, struct task_struct *idle); +#ifdef CONFIG_HOTPLUG_CPU + int (*cpu_kill)(unsigned int cpu); + void (*cpu_die)(unsigned int cpu); + int (*cpu_disable)(unsigned int cpu); +#endif +#endif +}; + +/* + * set platform specific SMP operations + */ +extern void smp_set_ops(struct smp_operations *); + #endif /* ifndef __ASM_ARM_SMP_H */ -- cgit v1.2.3 From ac6c7998712d55bd15aa2dd5ae85f5988c0cb526 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 27 Sep 2011 14:48:23 +0100 Subject: ARM: smp: Make SMP operations mandatory Now that all SMP platforms have been converted to use struct smp_operations, remove the "weak" attribute from the hooks in smp.c, and make the functions static wherever possible. Signed-off-by: Marc Zyngier Acked-by: Nicolas Pitre Signed-off-by: Arnd Bergmann --- arch/arm/include/asm/smp.h | 14 -------------- arch/arm/kernel/smp.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 23 deletions(-) (limited to 'arch/arm/include/asm/smp.h') diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index f79a9f51e322..3a8cfee26c91 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -60,15 +60,6 @@ extern int boot_secondary(unsigned int cpu, struct task_struct *); */ asmlinkage void secondary_start_kernel(void); -/* - * Perform platform specific initialisation of the specified CPU. - */ -extern void platform_secondary_init(unsigned int cpu); - -/* - * Initialize cpu_possible map, and enable coherency - */ -extern void platform_smp_prepare_cpus(unsigned int); /* * Initial data for bringing up a secondary CPU. @@ -81,15 +72,10 @@ struct secondary_data { extern struct secondary_data secondary_data; extern int __cpu_disable(void); -extern int platform_cpu_disable(unsigned int cpu); extern void __cpu_die(unsigned int cpu); extern void cpu_die(void); -extern void platform_cpu_die(unsigned int cpu); -extern int platform_cpu_kill(unsigned int cpu); -extern void platform_cpu_enable(unsigned int cpu); - extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d9241885521b..ac3ce029afb8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -110,25 +110,25 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) } /* platform specific SMP operations */ -void __attribute__((weak)) __init smp_init_cpus(void) +void __init smp_init_cpus(void) { if (smp_ops.smp_init_cpus) smp_ops.smp_init_cpus(); } -void __attribute__((weak)) __init platform_smp_prepare_cpus(unsigned int max_cpus) +static void __init platform_smp_prepare_cpus(unsigned int max_cpus) { if (smp_ops.smp_prepare_cpus) smp_ops.smp_prepare_cpus(max_cpus); } -void __attribute__((weak)) __cpuinit platform_secondary_init(unsigned int cpu) +static void __cpuinit platform_secondary_init(unsigned int cpu) { if (smp_ops.smp_secondary_init) smp_ops.smp_secondary_init(cpu); } -int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { if (smp_ops.smp_boot_secondary) return smp_ops.smp_boot_secondary(cpu, idle); @@ -138,20 +138,20 @@ int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task #ifdef CONFIG_HOTPLUG_CPU static void percpu_timer_stop(void); -int __attribute__((weak)) platform_cpu_kill(unsigned int cpu) +static int platform_cpu_kill(unsigned int cpu) { if (smp_ops.cpu_kill) return smp_ops.cpu_kill(cpu); return 1; } -void __attribute__((weak)) platform_cpu_die(unsigned int cpu) +static void platform_cpu_die(unsigned int cpu) { if (smp_ops.cpu_die) smp_ops.cpu_die(cpu); } -int __attribute__((weak)) platform_cpu_disable(unsigned int cpu) +static int platform_cpu_disable(unsigned int cpu) { if (smp_ops.cpu_disable) return smp_ops.cpu_disable(cpu); @@ -166,7 +166,7 @@ int __attribute__((weak)) platform_cpu_disable(unsigned int cpu) /* * __cpu_disable runs on the processor to be shutdown. */ -int __cpu_disable(void) +int __cpuinit __cpu_disable(void) { unsigned int cpu = smp_processor_id(); int ret; @@ -209,7 +209,7 @@ static DECLARE_COMPLETION(cpu_died); * 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) +void __cpuinit __cpu_die(unsigned int cpu) { if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { pr_err("CPU%u: cpu didn't die\n", cpu); -- cgit v1.2.3 From 28e8e29c616f947348cc66bea684d0035c76021a Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 12 Jun 2012 11:16:27 +0100 Subject: ARM: consolidate pen_release instead of having per platform definitions Almost each SMP platform defines pen_release to manage booting secondary CPUs. This of course clashes with the single zImage effort. Add the pen_release definition to the ARM SMP code, and remove all others. This should only be used by platforms which lack any kind of CPU power management... Reported-by: Arnd Bergmann Signed-off-by: Marc Zyngier Acked-by: Nicolas Pitre Signed-off-by: Arnd Bergmann --- arch/arm/include/asm/smp.h | 1 + arch/arm/kernel/smp.c | 6 ++++++ arch/arm/mach-exynos/hotplug.c | 2 -- arch/arm/mach-exynos/platsmp.c | 7 ------- arch/arm/mach-msm/hotplug.c | 2 -- arch/arm/mach-msm/platsmp.c | 5 ----- arch/arm/mach-realview/hotplug.c | 2 -- arch/arm/mach-spear13xx/hotplug.c | 2 -- arch/arm/mach-spear13xx/platsmp.c | 5 ----- arch/arm/mach-ux500/hotplug.c | 2 -- arch/arm/mach-ux500/platsmp.c | 6 ------ arch/arm/mach-vexpress/hotplug.c | 2 -- arch/arm/plat-versatile/platsmp.c | 6 ------ 13 files changed, 7 insertions(+), 41 deletions(-) (limited to 'arch/arm/include/asm/smp.h') diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 3a8cfee26c91..2e3be16c6766 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -70,6 +70,7 @@ struct secondary_data { void *stack; }; extern struct secondary_data secondary_data; +extern volatile int pen_release; extern int __cpu_disable(void); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index ac3ce029afb8..aa4ffe6e5ecf 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -51,6 +51,12 @@ */ struct secondary_data secondary_data; +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + enum ipi_msg_type { IPI_TIMER = 2, IPI_RESCHEDULE, diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index edccc36dd692..f4d7dd20cdac 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -23,8 +23,6 @@ #include "common.h" -extern volatile int pen_release; - static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 3fad8ad3f92c..8d57e4223bdb 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -39,13 +39,6 @@ extern void exynos4_secondary_startup(void); #define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ S5P_INFORM5 : S5P_VA_SYSRAM) -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ - -volatile int __cpuinitdata pen_release = -1; - /* * Write pen_release in a way that is guaranteed to be visible to all * observers, irrespective of whether they're taking part in coherency diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c index fedaa25b2935..002ac1e47235 100644 --- a/arch/arm/mach-msm/hotplug.c +++ b/arch/arm/mach-msm/hotplug.c @@ -15,8 +15,6 @@ #include "core.h" -extern volatile int pen_release; - static inline void cpu_enter_lowpower(void) { /* Just flush the cache. Changing the coherency is not yet diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index ba3c4b0d523d..57af32ef75ed 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -35,11 +35,6 @@ #define GIC_PPI_EDGE_MASK 0xFFFFD7FF extern void msm_secondary_startup(void); -/* - * control for which core is the next to come out of the secondary - * boot "holding pen". - */ -volatile int pen_release = -1; static DEFINE_SPINLOCK(boot_lock); diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index fef4f4495225..53818e5cd3ad 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c @@ -16,8 +16,6 @@ #include #include -extern volatile int pen_release; - static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/mach-spear13xx/hotplug.c b/arch/arm/mach-spear13xx/hotplug.c index 485fd4367bb1..a7d2dd11a4f2 100644 --- a/arch/arm/mach-spear13xx/hotplug.c +++ b/arch/arm/mach-spear13xx/hotplug.c @@ -17,8 +17,6 @@ #include #include -extern volatile int pen_release; - static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c index 806343c7b5d8..2eaa3fa7b432 100644 --- a/arch/arm/mach-spear13xx/platsmp.c +++ b/arch/arm/mach-spear13xx/platsmp.c @@ -21,11 +21,6 @@ #include #include -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; static DEFINE_SPINLOCK(boot_lock); static void __iomem *scu_base = IOMEM(VA_SCU_BASE); diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index b8e4d9ed62d8..2f6af259015d 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c @@ -17,8 +17,6 @@ #include -extern volatile int pen_release; - /* * platform-specific code to shutdown a CPU * diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index b6f4e0e787ec..d60873ee38bf 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -27,12 +27,6 @@ /* This is called from headsmp.S to wakeup the secondary core */ extern void u8500_secondary_startup(void); -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int pen_release = -1; - /* * Write pen_release in a way that is guaranteed to be visible to all * observers, irrespective of whether they're taking part in coherency diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c index 734423a39e7c..a141b98d84fe 100644 --- a/arch/arm/mach-vexpress/hotplug.c +++ b/arch/arm/mach-vexpress/hotplug.c @@ -16,8 +16,6 @@ #include #include -extern volatile int pen_release; - static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 39e60ac4fe65..04ca4937d8ca 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -19,12 +19,6 @@ #include #include -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; - /* * Write pen_release in a way that is guaranteed to be visible to all * observers, irrespective of whether they're taking part in coherency -- cgit v1.2.3