From f0eab3889e4b5b71e1609c9850f652f06a812cf5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 28 Dec 2011 16:44:06 +0900 Subject: ARM: mach-shmobile: Fix headsmp.S code to use CPUINIT Convert the low level SMP assembly code for SH-Mobile ARM from using the INIT to the CPUINIT section. This unbreaks onlining of CPUs using the CPU hotplug interface: echo 1 > /sys/devices/system/cpu/cpu1/online Without this fix the reset vector code used by CPU hotplug will be freed as init section data and CPU cores cannot be brought online. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/headsmp.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index 26079d933d9..6ac015c8920 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -14,7 +14,7 @@ #include #include - __INIT + __CPUINIT /* * Reset vector for secondary CPUs. -- cgit v1.2.3-70-g09d2 From 8b306796995609c281f6d32b3cbaa814551ad5ac Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 28 Dec 2011 16:47:16 +0900 Subject: ARM: mach-shmobile: Allow SoC specific CPU kill code Add the function shmobile_platform_kill_cpu() to allow SoC specific code to tie in their CPU shutdown code. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/hotplug.c | 3 ++- arch/arm/mach-shmobile/include/mach/common.h | 1 + arch/arm/mach-shmobile/platsmp.c | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index 238a0d97d2d..aee3a1088a5 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c @@ -12,10 +12,11 @@ #include #include #include +#include int platform_cpu_kill(unsigned int cpu) { - return 1; + return shmobile_platform_cpu_kill(cpu); } void platform_cpu_die(unsigned int cpu) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index be78a2c73db..8b8d80c2a51 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -4,6 +4,7 @@ extern struct sys_timer shmobile_timer; extern void shmobile_setup_console(void); extern void shmobile_secondary_vector(void); +extern int shmobile_platform_cpu_kill(unsigned int cpu); struct clk; extern int clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *); diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index c49a833bf9b..3f3325d4206 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -37,6 +37,11 @@ static void __init shmobile_smp_prepare_cpus(void) sh73a0_smp_prepare_cpus(); } +int shmobile_platform_cpu_kill(unsigned int cpu) +{ + return 1; +} + void __cpuinit platform_secondary_init(unsigned int cpu) { trace_hardirqs_off(); -- cgit v1.2.3-70-g09d2 From 1229835ccb6d7ea2b36230121205be95c88eca88 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 28 Dec 2011 16:53:16 +0900 Subject: ARM: mach-shmobile: Flush caches in platform_cpu_die() Add cache flushing code to the SH-Mobile specific CPU hotplug implementation. While at it, add a cpu mask to make sure the cache flushing code is finished in platform_cpu_die() before letting the SoC-specific code in shmobile_platform_cpu_kill() proceed with turning off power. Without this code CPU hotplug offline fails when cache is enabled on Cortex-A9 based SoCs. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/hotplug.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index aee3a1088a5..828d22f3af5 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c @@ -12,15 +12,43 @@ #include #include #include +#include +#include #include +#include + +static cpumask_t dead_cpus; int platform_cpu_kill(unsigned int cpu) { - return shmobile_platform_cpu_kill(cpu); + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (cpumask_test_cpu(cpu, &dead_cpus)) + return shmobile_platform_cpu_kill(cpu); + + mdelay(1); + } + + return 0; } void platform_cpu_die(unsigned int cpu) { + /* hardware shutdown code running on the CPU that is being offlined */ + flush_cache_all(); + dsb(); + + /* notify platform_cpu_kill() that hardware shutdown is finished */ + cpumask_set_cpu(cpu, &dead_cpus); + + /* wait for SoC code in platform_cpu_kill() to shut off CPU core + * power. CPU bring up starts from the reset vector. + */ while (1) { /* * here's the WFI @@ -34,6 +62,7 @@ void platform_cpu_die(unsigned int cpu) int platform_cpu_disable(unsigned int cpu) { + cpumask_clear_cpu(cpu, &dead_cpus); /* * we don't allow CPU 0 to be shutdown (it is still too special * e.g. clock tick interrupts) -- cgit v1.2.3-70-g09d2