[PATCH v6 15/15] ARM: hotplug: add cpu_lowpower as an alternative to cpu_die
Marc Zyngier
marc.zyngier at arm.com
Tue Feb 7 19:30:59 EST 2012
Most platforms don't actually implement cpu_die, but instead
a "go into low power mode" operation.
Factor these similar implementations into a single one called
from platform_cpu_die().
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Colin Cross <ccross at android.com>
Cc: David Brown <davidb at codeaurora.org>
Cc: Kukjin Kim <kgene.kim at samsung.com>
Cc: Linus Walleij <linus.walleij at stericsson.com>
Cc: Nicolas Pitre <nico at fluxnic.net>
Cc: Santosh Shilimkar <santosh.shilimkar at ti.com>
Cc: Stephen Warren <swarren at nvidia.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
arch/arm/include/asm/soc.h | 1 +
arch/arm/kernel/smp.c | 16 ++++++++-
arch/arm/mach-exynos/common.h | 2 +-
arch/arm/mach-exynos/hotplug.c | 27 +--------------
arch/arm/mach-exynos/platsmp.c | 2 +-
arch/arm/mach-msm/core.h | 2 +-
arch/arm/mach-msm/hotplug.c | 22 +-----------
arch/arm/mach-msm/platsmp.c | 2 +-
arch/arm/mach-realview/core.h | 2 +-
arch/arm/mach-realview/hotplug.c | 27 +--------------
arch/arm/mach-realview/platsmp.c | 2 +-
arch/arm/mach-tegra/common.h | 2 +-
arch/arm/mach-tegra/hotplug.c | 53 ++++--------------------------
arch/arm/mach-tegra/platsmp.c | 2 +-
arch/arm/mach-ux500/hotplug.c | 14 +-------
arch/arm/mach-ux500/include/mach/setup.h | 2 +-
arch/arm/mach-ux500/platsmp.c | 2 +-
arch/arm/mach-vexpress/core.h | 2 +-
arch/arm/mach-vexpress/hotplug.c | 27 +--------------
arch/arm/mach-vexpress/platsmp.c | 2 +-
20 files changed, 44 insertions(+), 167 deletions(-)
diff --git a/arch/arm/include/asm/soc.h b/arch/arm/include/asm/soc.h
index 1bcc58c..f1b6c45 100644
--- a/arch/arm/include/asm/soc.h
+++ b/arch/arm/include/asm/soc.h
@@ -38,6 +38,7 @@ struct arm_soc_smp_ops {
#ifdef CONFIG_HOTPLUG_CPU
int (*cpu_kill)(unsigned int cpu);
void (*cpu_die)(unsigned int cpu);
+ void (*cpu_lowpower)(unsigned int cpu, int *spurious);
int (*cpu_disable)(unsigned int cpu);
#endif
};
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e0d1622..34318aa 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -202,8 +202,20 @@ static int __cpuinit platform_cpu_kill(unsigned int cpu)
static void __cpuinit platform_cpu_die(unsigned int cpu)
{
- if (soc_smp_ops && soc_smp_ops->cpu_die)
- soc_smp_ops->cpu_die(cpu);
+ if (soc_smp_ops) {
+ if (soc_smp_ops->cpu_die) {
+ soc_smp_ops->cpu_die(cpu);
+ return;
+ }
+
+ if (soc_smp_ops->cpu_lowpower) {
+ int spurious = 0;
+ soc_smp_ops->cpu_lowpower(cpu, &spurious);
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n",
+ cpu, spurious);
+ }
+ }
}
static int __cpuinit platform_cpu_disable(unsigned int cpu)
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index f13631a..d664f6e 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -31,7 +31,7 @@ extern struct arm_soc_smp_init_ops exynos4_soc_smp_init_ops;
extern struct arm_soc_smp_ops exynos4_soc_smp_ops;
extern struct arm_soc_desc exynos4_soc_desc;
-extern void exynos4_cpu_die(unsigned int cpu);
+extern void exynos4_cpu_lowpower(unsigned int cpu, int *spurious);
#ifdef CONFIG_ARCH_EXYNOS
extern int exynos_init(void);
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index be7a96b..aed75cb 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -62,8 +62,9 @@ static inline void cpu_leave_lowpower(void)
: "cc");
}
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+void exynos4_cpu_lowpower(unsigned int cpu, int *spurious)
{
+ cpu_enter_lowpower();
for (;;) {
/* make cpu1 to be turned off at next WFI command */
@@ -94,29 +95,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
*/
(*spurious)++;
}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void exynos4_cpu_die(unsigned int cpu)
-{
- int spurious = 0;
-
- /*
- * we're ready for shutdown now, so do it
- */
- cpu_enter_lowpower();
- platform_do_lowpower(cpu, &spurious);
-
- /*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
- */
cpu_leave_lowpower();
-
- if (spurious)
- pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 4d22c2a..8469ac8 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -208,7 +208,7 @@ struct arm_soc_smp_ops exynos4_soc_smp_ops __initdata = {
.smp_boot_secondary = exynos4_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = exynos4_cpu_die,
+ .cpu_lowpower = exynos4_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-msm/core.h b/arch/arm/mach-msm/core.h
index 623474a..a5c50c4 100644
--- a/arch/arm/mach-msm/core.h
+++ b/arch/arm/mach-msm/core.h
@@ -4,4 +4,4 @@ extern struct arm_soc_smp_init_ops msm_soc_smp_init_ops;
extern struct arm_soc_smp_ops msm_soc_smp_ops;
extern struct arm_soc_desc msm_soc_desc;
-extern void msm_cpu_die(unsigned int cpu);
+extern void msm_cpu_lowpower(unsigned int cpu, int *spurious);
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index d0f79e8..6e6ed2d 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -28,9 +28,10 @@ static inline void cpu_leave_lowpower(void)
{
}
-static inline void platform_do_lowpower(unsigned int cpu)
+void msm_cpu_lowpower(unsigned int cpu, int *spurious)
{
/* Just enter wfi for now. TODO: Properly shut off the cpu. */
+ cpu_enter_lowpower();
for (;;) {
/*
* here's the WFI
@@ -57,24 +58,5 @@ static inline void platform_do_lowpower(unsigned int cpu)
*/
pr_debug("CPU%u: spurious wakeup call\n", cpu);
}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void msm_cpu_die(unsigned int cpu)
-{
- /*
- * we're ready for shutdown now, so do it
- */
- cpu_enter_lowpower();
- platform_do_lowpower(cpu);
-
- /*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
- */
cpu_leave_lowpower();
}
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f7e27d9..5e153cf 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -184,7 +184,7 @@ struct arm_soc_smp_ops msm_soc_smp_ops __initdata = {
.smp_boot_secondary = msm_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = msm_cpu_die,
+ .cpu_lowpower = msm_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index dd4bcdb..b593b36 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -71,6 +71,6 @@ extern struct arm_soc_desc realview_soc_desc;
extern struct arm_soc_smp_init_ops realview_soc_smp_init_ops;
extern struct arm_soc_smp_ops realview_soc_smp_ops;
-extern void realview_cpu_die(unsigned int cpu);
+extern void realview_cpu_lowpower(unsigned int cpu, int *spurious);
#endif
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index 12af634..4d45d07 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -54,13 +54,14 @@ static inline void cpu_leave_lowpower(void)
: "cc");
}
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+void realview_cpu_lowpower(unsigned int cpu, int *spurious)
{
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
* code will have already disabled interrupts
*/
+ cpu_enter_lowpower();
for (;;) {
/*
* here's the WFI
@@ -86,29 +87,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
*/
(*spurious)++;
}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void realview_cpu_die(unsigned int cpu)
-{
- int spurious = 0;
-
- /*
- * we're ready for shutdown now, so do it
- */
- cpu_enter_lowpower();
- platform_do_lowpower(cpu, &spurious);
-
- /*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
- */
cpu_leave_lowpower();
-
- if (spurious)
- pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 5b7535d..eb6b532 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -90,7 +90,7 @@ struct arm_soc_smp_ops realview_soc_smp_ops __initdata = {
.smp_boot_secondary = versatile_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = realview_cpu_die,
+ .cpu_lowpower = realview_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
index b02cc87..38b9ea4 100644
--- a/arch/arm/mach-tegra/common.h
+++ b/arch/arm/mach-tegra/common.h
@@ -6,4 +6,4 @@ struct arm_soc_smp_ops;
extern struct arm_soc_smp_init_ops tegra_soc_smp_init_ops;
extern struct arm_soc_smp_ops tegra_soc_smp_ops;
-extern void tegra_cpu_die(unsigned int cpu);
+extern void tegra_cpu_lowpower(unsigned int cpu, int *spurious);
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index 15433b2..455a077 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -52,61 +52,22 @@ static inline void cpu_leave_lowpower(void)
: "cc");
}
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+void tegra_cpu_lowpower(unsigned int cpu, int *spurious)
{
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
* code will have already disabled interrupts
*/
- for (;;) {
- /*
- * here's the WFI
- */
- asm(".word 0xe320f003\n"
- :
- :
- : "memory", "cc");
-
- /*if (pen_release == cpu) {*/
- /*
- * OK, proper wakeup, we're done
- */
- break;
- /*}*/
-
- /*
- * Getting here, means that we have come out of WFI without
- * having been woken up - this shouldn't happen
- *
- * Just note it happening - when we're woken, we can report
- * its occurrence.
- */
- (*spurious)++;
- }
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void tegra_cpu_die(unsigned int cpu)
-{
- int spurious = 0;
-
- /*
- * we're ready for shutdown now, so do it
- */
cpu_enter_lowpower();
- platform_do_lowpower(cpu, &spurious);
/*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
+ * here's the WFI
*/
- cpu_leave_lowpower();
+ asm("wfi\n"
+ :
+ :
+ : "memory", "cc");
- if (spurious)
- pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+ cpu_leave_lowpower();
}
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 4edc8ab..5d1593c 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -146,7 +146,7 @@ struct arm_soc_smp_ops tegra_soc_smp_ops __initdata = {
.smp_boot_secondary = tegra_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = tegra_cpu_die,
+ .cpu_lowpower = tegra_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index ec1c77f..c46b01d 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -19,7 +19,7 @@
extern volatile int pen_release;
-static inline void platform_do_lowpower(unsigned int cpu)
+void ux500_cpu_lowpower(unsigned int cpu, int *spurious)
{
flush_cache_all();
@@ -33,16 +33,6 @@ static inline void platform_do_lowpower(unsigned int cpu)
*/
break;
}
+ (*spurious)++;
}
}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void ux500_cpu_die(unsigned int cpu)
-{
- /* directly enter low power state, skipping secure registers */
- platform_do_lowpower(cpu);
-}
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 2935f85..127fd0b 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -55,6 +55,6 @@ extern struct arm_soc_smp_init_ops ux500_soc_smp_init_ops;
extern struct arm_soc_smp_ops ux500_soc_smp_ops;
extern struct arm_soc_desc ux500_soc_desc;
-extern void ux500_cpu_die(unsigned int cpu);
+extern void ux500_cpu_lowpower(unsigned int cpu, int *spurious)l
#endif /* __ASM_ARCH_SETUP_H */
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index bbd6480..f19ba4e 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -186,7 +186,7 @@ struct arm_soc_smp_ops ux500_soc_smp_ops __initdata = {
.smp_boot_secondary = ux500_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = ux500_cpu_die,
+ .cpu_lowpower = ux500_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index d9b1ec0..413e889 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -24,4 +24,4 @@ struct arm_soc_smp_ops;
extern struct arm_soc_smp_init_ops vexpress_soc_smp_init_ops;
extern struct arm_soc_smp_ops vexpress_soc_smp_ops;
-extern void vexpress_cpu_die(unsigned int cpu);
+extern void vexpress_cpu_lowpower(unsigned int cpu, int *spurious)
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
index e1a7fef..4c87adc 100644
--- a/arch/arm/mach-vexpress/hotplug.c
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -56,13 +56,14 @@ static inline void cpu_leave_lowpower(void)
: "cc");
}
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+void vexpress_cpu_lowpower(unsigned int cpu, int *spurious)
{
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
* code will have already disabled interrupts
*/
+ cpu_enter_lowpower();
for (;;) {
wfi();
@@ -82,29 +83,5 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
*/
(*spurious)++;
}
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void vexpress_cpu_die(unsigned int cpu)
-{
- int spurious = 0;
-
- /*
- * we're ready for shutdown now, so do it
- */
- cpu_enter_lowpower();
- platform_do_lowpower(cpu, &spurious);
-
- /*
- * bring this CPU back into the world of cache
- * coherency, and then restore interrupts
- */
cpu_leave_lowpower();
-
- if (spurious)
- pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index a5196f87..5630d2b 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -61,7 +61,7 @@ struct arm_soc_smp_ops vexpress_soc_smp_ops __initdata = {
.smp_boot_secondary = versatile_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = dummy_cpu_kill,
- .cpu_die = vexpress_cpu_die,
+ .cpu_lowpower = vexpress_cpu_lowpower,
.cpu_disable = dummy_cpu_disable,
#endif
};
--
1.7.3.4
More information about the linux-arm-kernel
mailing list