summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-08-10 10:20:38 +0800
committerAnson Huang <b20788@freescale.com>2011-08-10 14:45:00 +0800
commitd0ce95efe5383460745a4d42646117f8be8a96f2 (patch)
tree5cf86756160b853ee063420a5d452453e8e7ba13
parent37e7a70d761bbeb93d73672740c3eead25af58be (diff)
ENGR00154648 [Mx6]SMP hotplug sometimes hang
1. boot_secondary ioremap need unmap, or the stress test of hot-plug and suspend/resume will cause the virtual address space leak; 2. Disable secondary CPUs need done by CPU0, move the SRC_SCR setting to platform_cpu_kill. Signed-off-by: Anson Huang <b20788@freescale.com>
-rw-r--r--arch/arm/mach-mx6/plat_hotplug.c34
-rw-r--r--arch/arm/mach-mx6/platsmp.c2
2 files changed, 25 insertions, 11 deletions
diff --git a/arch/arm/mach-mx6/plat_hotplug.c b/arch/arm/mach-mx6/plat_hotplug.c
index 6ef057f6865a..3a124b084744 100644
--- a/arch/arm/mach-mx6/plat_hotplug.c
+++ b/arch/arm/mach-mx6/plat_hotplug.c
@@ -26,9 +26,28 @@
#include <linux/sched.h>
#include <asm/cacheflush.h>
-
+static atomic_t cpu_die_done = ATOMIC_INIT(0);
int platform_cpu_kill(unsigned int cpu)
{
+ void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+ unsigned int val;
+
+ val = jiffies;
+ /* wait secondary cpu to die, timeout is 500ms */
+ while (atomic_read(&cpu_die_done) == 0) {
+ if (time_after(jiffies, (unsigned long)(val + HZ / 2))) {
+ printk(KERN_WARNING "cpu %d: cpu could not die\n", cpu);
+ break;
+ }
+ }
+ /*
+ * we're ready for shutdown now, so do it
+ */
+ val = readl(src_base + SRC_SCR_OFFSET);
+ val &= ~(1 << (BP_SRC_SCR_CORES_DBG_RST + cpu));
+ writel(val, src_base + SRC_SCR_OFFSET);
+
+ atomic_set(&cpu_die_done, 0);
return 1;
}
@@ -38,23 +57,16 @@ int platform_cpu_kill(unsigned int cpu)
*/
void platform_cpu_die(unsigned int cpu)
{
- void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
- unsigned int val;
-
if (cpu == 0) {
printk(KERN_ERR "CPU0 can't be disabled!\n");
return;
}
+
flush_cache_all();
dsb();
- /*
- * we're ready for shutdown now, so do it
- */
- val = readl(src_base + SRC_SCR_OFFSET);
- val &= ~(1 << (BP_SRC_SCR_CORES_DBG_RST + cpu));
- writel(val, src_base + SRC_SCR_OFFSET);
-
+ /* tell cpu0 to kill me */
+ atomic_set(&cpu_die_done, 1);
for (;;) {
/*
* Execute WFI
diff --git a/arch/arm/mach-mx6/platsmp.c b/arch/arm/mach-mx6/platsmp.c
index 123063b31ecc..5155efe0d6da 100644
--- a/arch/arm/mach-mx6/platsmp.c
+++ b/arch/arm/mach-mx6/platsmp.c
@@ -104,6 +104,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
writel(0, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4);
smp_send_reschedule(cpu);
+ /* unmap iram base */
+ iounmap(boot_iram_base);
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish