Commit fb5d932a authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'imx-fixes-3.9-4' of git://git.linaro.org/people/shawnguo/linux-2.6 into fixes

From Shawn Guo <shawn.guo@linaro.org>:

The imx fixes for 3.9, take 4:

Running suspend/resume without no_console_suspend setting on kernel
cmdline will likely makes system hang.  It causesd by the sync issue
between imx_cpu_die() and imx_cpu_kill() call.  Fix the issue by
synchronizing the calls using cpu jumping argument register which is
free to use in kernel.

* tag 'imx-fixes-3.9-4' of git://git.linaro.org/people/shawnguo/linux-2.6:
  ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill
  ARM: imx: add dependency check for DEBUG_IMX_UART_PORT
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents cba26c5a 2f3edfd7
...@@ -495,6 +495,7 @@ config DEBUG_IMX_UART_PORT ...@@ -495,6 +495,7 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX53_UART || \ DEBUG_IMX53_UART || \
DEBUG_IMX6Q_UART DEBUG_IMX6Q_UART
default 1 default 1
depends on ARCH_MXC
help help
Choose UART port on which kernel low-level debug messages Choose UART port on which kernel low-level debug messages
should be output. should be output.
......
...@@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *); ...@@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *);
extern void imx_enable_cpu(int cpu, bool enable); extern void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr); extern void imx_set_cpu_jump(int cpu, void *jump_addr);
extern u32 imx_get_cpu_arg(int cpu);
extern void imx_set_cpu_arg(int cpu, u32 arg);
extern void v7_cpu_resume(void); extern void v7_cpu_resume(void);
extern u32 *pl310_get_save_ptr(void); extern u32 *pl310_get_save_ptr(void);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void) ...@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void)
void imx_cpu_die(unsigned int cpu) void imx_cpu_die(unsigned int cpu)
{ {
cpu_enter_lowpower(); cpu_enter_lowpower();
/*
* We use the cpu jumping argument register to sync with
* imx_cpu_kill() which is running on cpu0 and waiting for
* the register being cleared to kill the cpu.
*/
imx_set_cpu_arg(cpu, ~0);
cpu_do_idle(); cpu_do_idle();
} }
int imx_cpu_kill(unsigned int cpu) int imx_cpu_kill(unsigned int cpu)
{ {
unsigned long timeout = jiffies + msecs_to_jiffies(50);
while (imx_get_cpu_arg(cpu) == 0)
if (time_after(jiffies, timeout))
return 0;
imx_enable_cpu(cpu, false); imx_enable_cpu(cpu, false);
imx_set_cpu_arg(cpu, 0);
return 1; return 1;
} }
...@@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr) ...@@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
src_base + SRC_GPR1 + cpu * 8); src_base + SRC_GPR1 + cpu * 8);
} }
u32 imx_get_cpu_arg(int cpu)
{
cpu = cpu_logical_map(cpu);
return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
}
void imx_set_cpu_arg(int cpu, u32 arg)
{
cpu = cpu_logical_map(cpu);
writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
}
void imx_src_prepare_restart(void) void imx_src_prepare_restart(void)
{ {
u32 val; u32 val;
......
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