Commit 602bf409 authored by Shawn Guo's avatar Shawn Guo

ARM: imx6: exit coherency when shutting down a cpu

There is a system hang issue on imx6q which can easily be seen with
running a cpu hotplug stress testing (hotplug secondary cores from
user space via sysfs interface for thousands iterations).

It turns out that the issue is caused by coherency of the cpu that
is being shut down.  When shutting down a cpu, we need to have the
cpu exit coherency to prevent it from receiving cache, TLB, or BTB
maintenance operations broadcast by other CPUs in the cluster.

Copy cpu_enter_lowpower() and cpu_leave_lowpower() from mach-vexpress
to have coherency properly handled in platform_cpu_die(), thus fix
the issue.
Signed-off-by: default avatarShawn Guo <shawn.guo@linaro.org>
Cc: stable@kernel.org
parent eb5558dd
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <mach/common.h> #include <mach/common.h>
int platform_cpu_kill(unsigned int cpu) int platform_cpu_kill(unsigned int cpu)
...@@ -19,6 +20,44 @@ int platform_cpu_kill(unsigned int cpu) ...@@ -19,6 +20,44 @@ int platform_cpu_kill(unsigned int cpu)
return 1; return 1;
} }
static inline void cpu_enter_lowpower(void)
{
unsigned int v;
flush_cache_all();
asm volatile(
"mcr p15, 0, %1, c7, c5, 0\n"
" mcr p15, 0, %1, c7, c10, 4\n"
/*
* Turn off coherency
*/
" mrc p15, 0, %0, c1, c0, 1\n"
" bic %0, %0, %3\n"
" mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, %2\n"
" mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v)
: "r" (0), "Ir" (CR_C), "Ir" (0x40)
: "cc");
}
static inline void cpu_leave_lowpower(void)
{
unsigned int v;
asm volatile(
"mrc p15, 0, %0, c1, c0, 0\n"
" orr %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, %2\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (CR_C), "Ir" (0x40)
: "cc");
}
/* /*
* platform-specific code to shutdown a CPU * platform-specific code to shutdown a CPU
* *
...@@ -26,9 +65,10 @@ int platform_cpu_kill(unsigned int cpu) ...@@ -26,9 +65,10 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(unsigned int cpu) void platform_cpu_die(unsigned int cpu)
{ {
flush_cache_all(); cpu_enter_lowpower();
imx_enable_cpu(cpu, false); imx_enable_cpu(cpu, false);
cpu_do_idle(); cpu_do_idle();
cpu_leave_lowpower();
/* We should never return from idle */ /* We should never return from idle */
panic("cpu %d unexpectedly exit from shutdown\n", cpu); panic("cpu %d unexpectedly exit from shutdown\n", cpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment