ARM: zynq: Synchronise zynq_cpu_die/kill
Avoid races and add synchronisation between the arch specific
kill and die routines.
The same synchronisation issue was fixed on IMX platform
by this commit:
"ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill"
(sha1: 2f3edfd7e2
)
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
This commit is contained in:
parent
18aebf116b
commit
50c7960a45
|
@ -24,6 +24,8 @@ extern int zynq_early_slcr_init(void);
|
||||||
extern void zynq_slcr_system_reset(void);
|
extern void zynq_slcr_system_reset(void);
|
||||||
extern void zynq_slcr_cpu_stop(int cpu);
|
extern void zynq_slcr_cpu_stop(int cpu);
|
||||||
extern void zynq_slcr_cpu_start(int cpu);
|
extern void zynq_slcr_cpu_start(int cpu);
|
||||||
|
extern bool zynq_slcr_cpu_state_read(int cpu);
|
||||||
|
extern void zynq_slcr_cpu_state_write(int cpu, bool die);
|
||||||
extern u32 zynq_slcr_get_device_id(void);
|
extern u32 zynq_slcr_get_device_id(void);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
void zynq_platform_cpu_die(unsigned int cpu)
|
void zynq_platform_cpu_die(unsigned int cpu)
|
||||||
{
|
{
|
||||||
|
zynq_slcr_cpu_state_write(cpu, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* there is no power-control hardware on this platform, so all
|
* 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
|
* we can do is put the core into WFI; this is safe as the calling
|
||||||
|
|
|
@ -127,6 +127,12 @@ static void zynq_secondary_init(unsigned int cpu)
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
static int zynq_cpu_kill(unsigned cpu)
|
static int zynq_cpu_kill(unsigned cpu)
|
||||||
{
|
{
|
||||||
|
unsigned long timeout = jiffies + msecs_to_jiffies(50);
|
||||||
|
|
||||||
|
while (zynq_slcr_cpu_state_read(cpu))
|
||||||
|
if (time_after(jiffies, timeout))
|
||||||
|
return 0;
|
||||||
|
|
||||||
zynq_slcr_cpu_stop(cpu);
|
zynq_slcr_cpu_stop(cpu);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,8 @@ void zynq_slcr_cpu_start(int cpu)
|
||||||
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
|
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
|
||||||
reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu);
|
reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu);
|
||||||
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
|
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
|
||||||
|
|
||||||
|
zynq_slcr_cpu_state_write(cpu, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,8 +156,47 @@ void zynq_slcr_cpu_stop(int cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zynq_slcr_init - Regular slcr driver init
|
* zynq_slcr_cpu_state - Read/write cpu state
|
||||||
|
* @cpu: cpu number
|
||||||
*
|
*
|
||||||
|
* SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1)
|
||||||
|
* 0 means cpu is running, 1 cpu is going to die.
|
||||||
|
*
|
||||||
|
* Return: true if cpu is running, false if cpu is going to die
|
||||||
|
*/
|
||||||
|
bool zynq_slcr_cpu_state_read(int cpu)
|
||||||
|
{
|
||||||
|
u32 state;
|
||||||
|
|
||||||
|
state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
|
||||||
|
state &= 1 << (31 - cpu);
|
||||||
|
|
||||||
|
return !state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zynq_slcr_cpu_state - Read/write cpu state
|
||||||
|
* @cpu: cpu number
|
||||||
|
* @die: cpu state - true if cpu is going to die
|
||||||
|
*
|
||||||
|
* SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1)
|
||||||
|
* 0 means cpu is running, 1 cpu is going to die.
|
||||||
|
*/
|
||||||
|
void zynq_slcr_cpu_state_write(int cpu, bool die)
|
||||||
|
{
|
||||||
|
u32 state, mask;
|
||||||
|
|
||||||
|
state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
|
||||||
|
mask = 1 << (31 - cpu);
|
||||||
|
if (die)
|
||||||
|
state |= mask;
|
||||||
|
else
|
||||||
|
state &= ~mask;
|
||||||
|
writel(state, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zynq_slcr_init - Regular slcr driver init
|
||||||
* Return: 0 on success, negative errno otherwise.
|
* Return: 0 on success, negative errno otherwise.
|
||||||
*
|
*
|
||||||
* Called early during boot from platform code to remap SLCR area.
|
* Called early during boot from platform code to remap SLCR area.
|
||||||
|
|
Loading…
Reference in New Issue