This patch extracts the common code of the cpu hotplug feature across arm platforms. The goal is to only keep the specific stuff of the platform in the sub-architecture. I have created a hotplug.c file in the arm/common directory after studying the cpu hotplug code of omap2, realview, s5pv310, ux500 and tegra. I have extracted 3 main platform dependent functions: -platform_enter_lowpower which prepares the platform for low power. -platform_do_lowpower on which the cpu will loop until it becomes really plugged (spurious wake up). This function must returned the cpu Id in order to leave the unplug state. -platform_leave_lowpower which restore the platform context.
An ux500 patch is available which uses the common/hotplug.c code. This patch is quite short because the idle / power down functions are not yet upstreamed Signed-off-by: Vincent Guittot <vincent.guit...@stericsson.com> --- arch/arm/Kconfig | 1 + arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/hotplug.c | 68 +++++++++------------------------------- arch/arm/mach-ux500/platsmp.c | 2 + 4 files changed, 20 insertions(+), 53 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ca96a44..ee74cf9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -797,6 +797,7 @@ config ARCH_U8500 select GENERIC_CLOCKEVENTS select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB + select USE_COMMON_ARM_HOTPLUG if HOTPLUG_CPU help Support for ST-Ericsson's Ux500 architecture diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 0612013..cb86197 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_USE_COMMON_ARM_HOTPLUG) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index b782a03..14a614f 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c @@ -6,70 +6,34 @@ * Based on ARM realview platform * * Author: Sundar Iyer <sundar.i...@stericsson.com> + * Author: Vincent Guittot <vincent.guit...@stericsson.com> * + * We only keep platform related code in the subarchitecture directory. + * The common code across platform has been moved into kernel/common directory */ -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/smp.h> -#include <linux/completion.h> -#include <asm/cacheflush.h> +#include <asm/hotplug.h> extern volatile int pen_release; -static DECLARE_COMPLETION(cpu_killed); - -static inline void platform_do_lowpower(unsigned int cpu) -{ - flush_cache_all(); - - /* we put the platform to just WFI */ - for (;;) { - __asm__ __volatile__("dsb\n\t" "wfi\n\t" - : : : "memory"); - if (pen_release == cpu) { - /* - * OK, proper wakeup, we're done - */ - break; - } - } -} - -int platform_cpu_kill(unsigned int cpu) +/* Default implementation that will be used if not override + * by power specific implementation + */ +void __attribute__((weak)) platform_enter_lowpower(unsigned int cpu) { - return wait_for_completion_timeout(&cpu_killed, 5000); + return; } -/* - * platform-specific code to shutdown a CPU - * - * Called with IRQs disabled - */ -void platform_cpu_die(unsigned int cpu) +int __attribute__((weak)) platform_do_lowpower(unsigned int cpu) { -#ifdef DEBUG - unsigned int this_cpu = hard_smp_processor_id(); - - if (cpu != this_cpu) { - printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", - this_cpu, cpu); - BUG(); - } -#endif - - printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); - complete(&cpu_killed); + __asm__ __volatile__("dsb\n\t" "wfi\n\t" + : : : "memory"); - /* directly enter low power state, skipping secure registers */ - platform_do_lowpower(cpu); + return pen_release; } -int platform_cpu_disable(unsigned int cpu) +void __attribute__((weak)) platform_leave_lowpower(unsigned int cpu) { - /* - * we don't allow CPU 0 to be shutdown (it is still too special - * e.g. clock tick interrupts) - */ - return cpu == 0 ? -EPERM : 0; + return; } + diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 9e4c678..3074260 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -51,6 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * pen, then head off into the C entry point */ pen_release = -1; + smp_wmb(); /* * Synchronise with the boot thread. @@ -82,6 +83,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { + smp_rmb(); if (pen_release == -1) break; } -- 1.7.0.4 _______________________________________________ linaro-dev mailing list linaro-dev@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-dev