Re: 答复: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
On Mon, Dec 01, 2014 at 05:53:16AM +, zhuoyu.zh...@freescale.com wrote: > > > > -邮件原件- > > 发件人: Mark Rutland [mailto:mark.rutl...@arm.com] > > 发送时间: Friday, November 28, 2014 6:33 PM > > 收件人: Zhang Zhuoyu-B46552 > > 抄送: linux-kernel@vger.kernel.org; ker...@pengutronix.de; linux-arm- > > ker...@lists.infradead.org; Li Yang-Leo-R58472; linuxppc- > > rele...@linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336; > > li...@arm.linux.org.uk > > 主题: Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support > > > > On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: > > > From: Zhang Zhuoyu > > > > > > This implements CPU hotplug for ls1. When cpu is down, it will be put > > > in WFI state. When cpu is up, it will always soft reset and boots up > > > the same path as a cold boot. > > > > > > Signed-off-by: Zhang Zhuoyu > > > --- > > > arch/arm/mach-imx/common.h | 4 ++ > > > arch/arm/mach-imx/hotplug.c | 25 + > > > arch/arm/mach-imx/platsmp.c | 132 > > +++- > > > arch/arm/mach-imx/src.c | 21 +++ > > > 4 files changed, 169 insertions(+), 13 deletions(-) > > > > > > > [...] > > > > > + > > > +/* > > > + * For LS102x platforms, shutdowning a CPU is not supported by hardware. > > > + * So we just put the offline CPU into lower-power state here. > > > + */ > > > +void __ref ls1021a_cpu_die(unsigned int cpu) { > > > + v7_exit_coherency_flush(louis); > > > + > > > + /* LS1021a platform can't really power down a CPU, so we > > > +* just put it into WFI state here. > > > +*/ > > > + wfi(); > > > +} > > > + > > > +int ls1021a_cpu_kill(unsigned int cpu) { > > > + unsigned long timeout = jiffies + msecs_to_jiffies(50); > > > + > > > + while (!ls1_get_cpu_arg(cpu)) > > > + if (time_after(jiffies, timeout)) > > > + return 0; > > > + return 1; > > > +} > > > > While simpler than the last posting [1], this is still no better, and > > Russell's > > comments [2] still apply, so this is still unacceptable. > > > > If the CPU does not leave the kernel entirely, it is not CPU hotplug. > > As this stands, this is completely incompatible with kexec and suspend. > > > > There are some hardware limitation for ls1 platform, core cannot power > down, so the only thing we can do here is to put it into low-power > state when CPU offline. Which means that cpu_die/cpu_kill aren't doing their jobs, because the CPU is still executing the WFI from the kernel text. > For suspend compatibility, I quote Leo's comments in last posting, "I > don't think it breaks the system suspend case as tasks and interrupts > have been moved out of the non-booting CPU." > > For kexec compatibility, it means we should always reset core and > boots up the same path as a cold boot when CPU re-online. That's > exactly what we are doing in ls1021a_reset_secondary(). I will explain > it in detail below. The issues is that until said explicit reset, the CPUs are still executing the WFI from original kernel text, which will almost certainly be clobbered before any subsequent kernel may attempt to bring them online. Any stray interrupt could wake them during this time, leading to disaster. A WFI may complete for reasons other than an interrupt, as documented in the ARM ARM, so a single WFI cannot be relied upon to keep a CPU in a low power state even in the absence of interrupts. Given that the surrounding text may be clobbered it is not possible to surround the WFI in a loop to accomodate this. > > [...] > > > > > +static int ls1021a_reset_secondary(unsigned int cpu) { > > > + u32 tmp; > > > + > > > + if (!scfg_base || !dcfg_base) > > > + return -ENOMEM; > > > + > > > + writel_relaxed(secondary_pre_boot_entry, > > > + dcfg_base + DCFG_CCSR_SCRATCHRW1); > > > + > > > + /* Apply LS1021A specific to write to the BE SCFG space */ > > > + tmp = ioread32be(scfg_base + SCFG_REVCR); > > > + iowrite32be(0x, scfg_base + SCFG_REVCR); > > > + > > > + /* Soft reset secondary core */ > > > + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); > > > + iowrite32be(0x8000, scfg_base + > > > +
RE: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
> -Original Message- > From: Mark Rutland [mailto:mark.rutl...@arm.com] > Sent: Friday, November 28, 2014 6:33 PM > To: Zhang Zhuoyu-B46552 > Cc: linux-kernel@vger.kernel.org; ker...@pengutronix.de; linux-arm- > ker...@lists.infradead.org; Li Yang-Leo-R58472; linuxppc- > rele...@linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336; > li...@arm.linux.org.uk > Subject: Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support > > On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: > > From: Zhang Zhuoyu > > > > This implements CPU hotplug for ls1. When cpu is down, it will be put > > in WFI state. When cpu is up, it will always soft reset and boots up > > the same path as a cold boot. > > > > Signed-off-by: Zhang Zhuoyu > > --- > > arch/arm/mach-imx/common.h | 4 ++ > > arch/arm/mach-imx/hotplug.c | 25 + > > arch/arm/mach-imx/platsmp.c | 132 > +++- > > arch/arm/mach-imx/src.c | 21 +++ > > 4 files changed, 169 insertions(+), 13 deletions(-) > > > > [...] > > > + > > +/* > > + * For LS102x platforms, shutdowning a CPU is not supported by hardware. > > + * So we just put the offline CPU into lower-power state here. > > + */ > > +void __ref ls1021a_cpu_die(unsigned int cpu) { > > + v7_exit_coherency_flush(louis); > > + > > + /* LS1021a platform can't really power down a CPU, so we > > +* just put it into WFI state here. > > +*/ > > + wfi(); > > +} > > + > > +int ls1021a_cpu_kill(unsigned int cpu) { > > + unsigned long timeout = jiffies + msecs_to_jiffies(50); > > + > > + while (!ls1_get_cpu_arg(cpu)) > > + if (time_after(jiffies, timeout)) > > + return 0; > > + return 1; > > +} > > While simpler than the last posting [1], this is still no better, and > Russell's > comments [2] still apply, so this is still unacceptable. > > If the CPU does not leave the kernel entirely, it is not CPU hotplug. > As this stands, this is completely incompatible with kexec and suspend. > There are some hardware limitations for ls1 platform, core cannot power down, so the only thing we can do here is to put it into low-power state when CPU offline. For suspend compatibility, I quote Leo's comments in last posting, "I don't think it breaks the system suspend case as tasks and interrupts have been moved out of the non-booting CPU." For kexec compatibility, it means we should always reset core and boots up the same path as a cold boot when CPU re-online. That's exactly what we are doing in ls1021a_reset_secondary(). I will explain it in detail below. > [...] > > > +static int ls1021a_reset_secondary(unsigned int cpu) { > > + u32 tmp; > > + > > + if (!scfg_base || !dcfg_base) > > + return -ENOMEM; > > + > > + writel_relaxed(secondary_pre_boot_entry, > > + dcfg_base + DCFG_CCSR_SCRATCHRW1); > > + > > + /* Apply LS1021A specific to write to the BE SCFG space */ > > + tmp = ioread32be(scfg_base + SCFG_REVCR); > > + iowrite32be(0x, scfg_base + SCFG_REVCR); > > + > > + /* Soft reset secondary core */ > > + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); > > + iowrite32be(0x8000, scfg_base + > > + SCFG_CORE0_SFT_RST + STRIDE_4B * cpu); > > + > > + /* Release secondary core */ > > + iowrite32be(1 << cpu, dcfg_base + DCFG_CCSR_BRR); > > + > > + ls1021a_set_secondary_entry(); > > + > > + /* Disable core soft reset register */ > > + iowrite32be(0x0, scfg_base + SCFG_CORESRENCR); > > + > > + /* Revert back to the default */ > > + iowrite32be(tmp, scfg_base + SCFG_REVCR); > > + > > + return 0; > > +} > > + > > +static int ls1021a_boot_secondary(unsigned int cpu, struct > > +task_struct *idle) { > > + int ret = 0; > > + > > + if (system_state == SYSTEM_RUNNING) > > + ret = ls1021a_reset_secondary(cpu); > > + > > + udelay(1); > > + > > + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); > > + > > + return ret; > > +} > > How does this interact with the pseudo-hotplug above? > > Mark. When CPU come online, secondary core reset and boots up the same path as a cold boot: 1) Write 1 to core soft reset register SCFG_CORE1_SFT_RST will reset
RE: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
-Original Message- From: Mark Rutland [mailto:mark.rutl...@arm.com] Sent: Friday, November 28, 2014 6:33 PM To: Zhang Zhuoyu-B46552 Cc: linux-kernel@vger.kernel.org; ker...@pengutronix.de; linux-arm- ker...@lists.infradead.org; Li Yang-Leo-R58472; linuxppc- rele...@linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336; li...@arm.linux.org.uk Subject: Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: From: Zhang Zhuoyu zhuoyu.zh...@freescale.com This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will always soft reset and boots up the same path as a cold boot. Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com --- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/hotplug.c | 25 + arch/arm/mach-imx/platsmp.c | 132 +++- arch/arm/mach-imx/src.c | 21 +++ 4 files changed, 169 insertions(+), 13 deletions(-) [...] + +/* + * For LS102x platforms, shutdowning a CPU is not supported by hardware. + * So we just put the offline CPU into lower-power state here. + */ +void __ref ls1021a_cpu_die(unsigned int cpu) { + v7_exit_coherency_flush(louis); + + /* LS1021a platform can't really power down a CPU, so we +* just put it into WFI state here. +*/ + wfi(); +} + +int ls1021a_cpu_kill(unsigned int cpu) { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (!ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} While simpler than the last posting [1], this is still no better, and Russell's comments [2] still apply, so this is still unacceptable. If the CPU does not leave the kernel entirely, it is not CPU hotplug. As this stands, this is completely incompatible with kexec and suspend. There are some hardware limitations for ls1 platform, core cannot power down, so the only thing we can do here is to put it into low-power state when CPU offline. For suspend compatibility, I quote Leo's comments in last posting, I don't think it breaks the system suspend case as tasks and interrupts have been moved out of the non-booting CPU. For kexec compatibility, it means we should always reset core and boots up the same path as a cold boot when CPU re-online. That's exactly what we are doing in ls1021a_reset_secondary(). I will explain it in detail below. [...] +static int ls1021a_reset_secondary(unsigned int cpu) { + u32 tmp; + + if (!scfg_base || !dcfg_base) + return -ENOMEM; + + writel_relaxed(secondary_pre_boot_entry, + dcfg_base + DCFG_CCSR_SCRATCHRW1); + + /* Apply LS1021A specific to write to the BE SCFG space */ + tmp = ioread32be(scfg_base + SCFG_REVCR); + iowrite32be(0x, scfg_base + SCFG_REVCR); + + /* Soft reset secondary core */ + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); + iowrite32be(0x8000, scfg_base + + SCFG_CORE0_SFT_RST + STRIDE_4B * cpu); + + /* Release secondary core */ + iowrite32be(1 cpu, dcfg_base + DCFG_CCSR_BRR); + + ls1021a_set_secondary_entry(); + + /* Disable core soft reset register */ + iowrite32be(0x0, scfg_base + SCFG_CORESRENCR); + + /* Revert back to the default */ + iowrite32be(tmp, scfg_base + SCFG_REVCR); + + return 0; +} + +static int ls1021a_boot_secondary(unsigned int cpu, struct +task_struct *idle) { + int ret = 0; + + if (system_state == SYSTEM_RUNNING) + ret = ls1021a_reset_secondary(cpu); + + udelay(1); + + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + return ret; +} How does this interact with the pseudo-hotplug above? Mark. When CPU come online, secondary core reset and boots up the same path as a cold boot: 1) Write 1 to core soft reset register SCFG_CORE1_SFT_RST will reset the secondary core. Resetting means a totally new start to secondary core, it will re-initialization(TLB, Caches, MMU) just like a cold boot. 2) The reentry address of secondary core is determined by the DCFG_CCSR_SCRATCHRW1 register. Writing the secondary core reentry physic address to this register to make sure secondary core restart executing a new code section after reset. This can make sure it is compatible with kexec. 3) Set the corresponding bit of DCFG_CCSR_BRR to release secondary core to re-initialize itself again. Zhuoyu -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo
Re: 答复: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
On Mon, Dec 01, 2014 at 05:53:16AM +, zhuoyu.zh...@freescale.com wrote: -邮件原件- 发件人: Mark Rutland [mailto:mark.rutl...@arm.com] 发送时间: Friday, November 28, 2014 6:33 PM 收件人: Zhang Zhuoyu-B46552 抄送: linux-kernel@vger.kernel.org; ker...@pengutronix.de; linux-arm- ker...@lists.infradead.org; Li Yang-Leo-R58472; linuxppc- rele...@linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336; li...@arm.linux.org.uk 主题: Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: From: Zhang Zhuoyu zhuoyu.zh...@freescale.com This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will always soft reset and boots up the same path as a cold boot. Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com --- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/hotplug.c | 25 + arch/arm/mach-imx/platsmp.c | 132 +++- arch/arm/mach-imx/src.c | 21 +++ 4 files changed, 169 insertions(+), 13 deletions(-) [...] + +/* + * For LS102x platforms, shutdowning a CPU is not supported by hardware. + * So we just put the offline CPU into lower-power state here. + */ +void __ref ls1021a_cpu_die(unsigned int cpu) { + v7_exit_coherency_flush(louis); + + /* LS1021a platform can't really power down a CPU, so we +* just put it into WFI state here. +*/ + wfi(); +} + +int ls1021a_cpu_kill(unsigned int cpu) { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (!ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} While simpler than the last posting [1], this is still no better, and Russell's comments [2] still apply, so this is still unacceptable. If the CPU does not leave the kernel entirely, it is not CPU hotplug. As this stands, this is completely incompatible with kexec and suspend. There are some hardware limitation for ls1 platform, core cannot power down, so the only thing we can do here is to put it into low-power state when CPU offline. Which means that cpu_die/cpu_kill aren't doing their jobs, because the CPU is still executing the WFI from the kernel text. For suspend compatibility, I quote Leo's comments in last posting, I don't think it breaks the system suspend case as tasks and interrupts have been moved out of the non-booting CPU. For kexec compatibility, it means we should always reset core and boots up the same path as a cold boot when CPU re-online. That's exactly what we are doing in ls1021a_reset_secondary(). I will explain it in detail below. The issues is that until said explicit reset, the CPUs are still executing the WFI from original kernel text, which will almost certainly be clobbered before any subsequent kernel may attempt to bring them online. Any stray interrupt could wake them during this time, leading to disaster. A WFI may complete for reasons other than an interrupt, as documented in the ARM ARM, so a single WFI cannot be relied upon to keep a CPU in a low power state even in the absence of interrupts. Given that the surrounding text may be clobbered it is not possible to surround the WFI in a loop to accomodate this. [...] +static int ls1021a_reset_secondary(unsigned int cpu) { + u32 tmp; + + if (!scfg_base || !dcfg_base) + return -ENOMEM; + + writel_relaxed(secondary_pre_boot_entry, + dcfg_base + DCFG_CCSR_SCRATCHRW1); + + /* Apply LS1021A specific to write to the BE SCFG space */ + tmp = ioread32be(scfg_base + SCFG_REVCR); + iowrite32be(0x, scfg_base + SCFG_REVCR); + + /* Soft reset secondary core */ + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); + iowrite32be(0x8000, scfg_base + + SCFG_CORE0_SFT_RST + STRIDE_4B * cpu); + + /* Release secondary core */ + iowrite32be(1 cpu, dcfg_base + DCFG_CCSR_BRR); + + ls1021a_set_secondary_entry(); + + /* Disable core soft reset register */ + iowrite32be(0x0, scfg_base + SCFG_CORESRENCR); + + /* Revert back to the default */ + iowrite32be(tmp, scfg_base + SCFG_REVCR); + + return 0; +} + +static int ls1021a_boot_secondary(unsigned int cpu, struct +task_struct *idle) { + int ret = 0; + + if (system_state == SYSTEM_RUNNING) + ret = ls1021a_reset_secondary(cpu); + + udelay(1); + + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + return ret; +} How does this interact with the pseudo-hotplug above
Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: > From: Zhang Zhuoyu > > This implements CPU hotplug for ls1. When cpu is down, it will be put > in WFI state. When cpu is up, it will always soft reset and boots up > the same path as a cold boot. > > Signed-off-by: Zhang Zhuoyu > --- > arch/arm/mach-imx/common.h | 4 ++ > arch/arm/mach-imx/hotplug.c | 25 + > arch/arm/mach-imx/platsmp.c | 132 > +++- > arch/arm/mach-imx/src.c | 21 +++ > 4 files changed, 169 insertions(+), 13 deletions(-) > [...] > + > +/* > + * For LS102x platforms, shutdowning a CPU is not supported by hardware. > + * So we just put the offline CPU into lower-power state here. > + */ > +void __ref ls1021a_cpu_die(unsigned int cpu) > +{ > + v7_exit_coherency_flush(louis); > + > + /* LS1021a platform can't really power down a CPU, so we > +* just put it into WFI state here. > +*/ > + wfi(); > +} > + > +int ls1021a_cpu_kill(unsigned int cpu) > +{ > + unsigned long timeout = jiffies + msecs_to_jiffies(50); > + > + while (!ls1_get_cpu_arg(cpu)) > + if (time_after(jiffies, timeout)) > + return 0; > + return 1; > +} While simpler than the last posting [1], this is still no better, and Russell's comments [2] still apply, so this is still unacceptable. If the CPU does not leave the kernel entirely, it is not CPU hotplug. As this stands, this is completely incompatible with kexec and suspend. [...] > +static int ls1021a_reset_secondary(unsigned int cpu) > +{ > + u32 tmp; > + > + if (!scfg_base || !dcfg_base) > + return -ENOMEM; > + > + writel_relaxed(secondary_pre_boot_entry, > + dcfg_base + DCFG_CCSR_SCRATCHRW1); > + > + /* Apply LS1021A specific to write to the BE SCFG space */ > + tmp = ioread32be(scfg_base + SCFG_REVCR); > + iowrite32be(0x, scfg_base + SCFG_REVCR); > + > + /* Soft reset secondary core */ > + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); > + iowrite32be(0x8000, scfg_base + > + SCFG_CORE0_SFT_RST + STRIDE_4B * cpu); > + > + /* Release secondary core */ > + iowrite32be(1 << cpu, dcfg_base + DCFG_CCSR_BRR); > + > + ls1021a_set_secondary_entry(); > + > + /* Disable core soft reset register */ > + iowrite32be(0x0, scfg_base + SCFG_CORESRENCR); > + > + /* Revert back to the default */ > + iowrite32be(tmp, scfg_base + SCFG_REVCR); > + > + return 0; > +} > + > +static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle) > +{ > + int ret = 0; > + > + if (system_state == SYSTEM_RUNNING) > + ret = ls1021a_reset_secondary(cpu); > + > + udelay(1); > + > + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); > + > + return ret; > +} How does this interact with the pseudo-hotplug above? Mark. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
On Mon, Nov 24, 2014 at 05:28:09AM +, Zhuoyu Zhang wrote: From: Zhang Zhuoyu zhuoyu.zh...@freescale.com This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will always soft reset and boots up the same path as a cold boot. Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com --- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/hotplug.c | 25 + arch/arm/mach-imx/platsmp.c | 132 +++- arch/arm/mach-imx/src.c | 21 +++ 4 files changed, 169 insertions(+), 13 deletions(-) [...] + +/* + * For LS102x platforms, shutdowning a CPU is not supported by hardware. + * So we just put the offline CPU into lower-power state here. + */ +void __ref ls1021a_cpu_die(unsigned int cpu) +{ + v7_exit_coherency_flush(louis); + + /* LS1021a platform can't really power down a CPU, so we +* just put it into WFI state here. +*/ + wfi(); +} + +int ls1021a_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (!ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} While simpler than the last posting [1], this is still no better, and Russell's comments [2] still apply, so this is still unacceptable. If the CPU does not leave the kernel entirely, it is not CPU hotplug. As this stands, this is completely incompatible with kexec and suspend. [...] +static int ls1021a_reset_secondary(unsigned int cpu) +{ + u32 tmp; + + if (!scfg_base || !dcfg_base) + return -ENOMEM; + + writel_relaxed(secondary_pre_boot_entry, + dcfg_base + DCFG_CCSR_SCRATCHRW1); + + /* Apply LS1021A specific to write to the BE SCFG space */ + tmp = ioread32be(scfg_base + SCFG_REVCR); + iowrite32be(0x, scfg_base + SCFG_REVCR); + + /* Soft reset secondary core */ + iowrite32be(0x8000, scfg_base + SCFG_CORESRENCR); + iowrite32be(0x8000, scfg_base + + SCFG_CORE0_SFT_RST + STRIDE_4B * cpu); + + /* Release secondary core */ + iowrite32be(1 cpu, dcfg_base + DCFG_CCSR_BRR); + + ls1021a_set_secondary_entry(); + + /* Disable core soft reset register */ + iowrite32be(0x0, scfg_base + SCFG_CORESRENCR); + + /* Revert back to the default */ + iowrite32be(tmp, scfg_base + SCFG_REVCR); + + return 0; +} + +static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + int ret = 0; + + if (system_state == SYSTEM_RUNNING) + ret = ls1021a_reset_secondary(cpu); + + udelay(1); + + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + return ret; +} How does this interact with the pseudo-hotplug above? Mark. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
From: Zhang Zhuoyu This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will always soft reset and boots up the same path as a cold boot. Signed-off-by: Zhang Zhuoyu --- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/hotplug.c | 25 + arch/arm/mach-imx/platsmp.c | 132 +++- arch/arm/mach-imx/src.c | 21 +++ 4 files changed, 169 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59ce8f3..f7d2be5 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -92,6 +92,7 @@ void imx_print_silicon_rev(const char *cpu, int srev); void imx_enable_cpu(int cpu, bool enable); void imx_set_cpu_jump(int cpu, void *jump_addr); u32 imx_get_cpu_arg(int cpu); +u32 ls1_get_cpu_arg(int cpu); void imx_set_cpu_arg(int cpu, u32 arg); #ifdef CONFIG_SMP void v7_secondary_startup(void); @@ -134,6 +135,9 @@ void imx6sl_pm_init(void); void imx6sx_pm_init(void); void imx6q_pm_set_ccm_base(void __iomem *base); +extern void ls1021a_cpu_die(unsigned int cpu); +extern int ls1021a_cpu_kill(unsigned int cpu); + #ifdef CONFIG_PM void imx51_pm_init(void); void imx53_pm_init(void); diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index b35e99c..2ee5e46 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "common.h" @@ -68,3 +69,27 @@ int imx_cpu_kill(unsigned int cpu) imx_set_cpu_arg(cpu, 0); return 1; } + +/* + * For LS102x platforms, shutdowning a CPU is not supported by hardware. + * So we just put the offline CPU into lower-power state here. + */ +void __ref ls1021a_cpu_die(unsigned int cpu) +{ + v7_exit_coherency_flush(louis); + + /* LS1021a platform can't really power down a CPU, so we +* just put it into WFI state here. +*/ + wfi(); +} + +int ls1021a_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (!ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 7f27001..7735ebb 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -23,8 +24,24 @@ #include "common.h" #include "hardware.h" +#defineSCFG_CORE0_SFT_RST 0x130 +#defineSCFG_REVCR 0x200 +#defineSCFG_CORESRENCR 0x204 +#defineSCFG_SPARECR4 0x50C + +#defineDCFG_CCSR_BRR 0x0E4 +#defineDCFG_CCSR_SCRATCHRW10x200 + +#defineDCSR_RCPM2_DEBUG1 0x400 +#defineDCSR_RCPM2_DEBUG2 0x414 + +#defineSTRIDE_4B 4 + u32 g_diag_reg; static void __iomem *scu_base; +static void __iomem *dcfg_base; +static void __iomem *scfg_base; +static u32 secondary_pre_boot_entry; static struct map_desc scu_io_desc __initdata = { /* .virtual and .pfn are run-time assigned */ @@ -98,32 +115,121 @@ struct smp_operations imx_smp_ops __initdata = { #endif }; -#define DCFG_CCSR_SCRATCHRW1 0x200 - -static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int ls1021a_secondary_iomap(void) { - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + struct device_node *np; + int ret; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); + if (!np) { + pr_err("%s: failed to find dcfg node.\n", __func__); + ret = -EINVAL; + goto dcfg_err; + } + + dcfg_base = of_iomap(np, 0); + of_node_put(np); + if (!dcfg_base) { + pr_err("%s: failed to map dcfg.\n", __func__); + ret = -ENOMEM; + goto dcfg_err; + } + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-scfg"); + if (!np) { + pr_err("%s: failed to find scfg node.\n", __func__); + ret = -EINVAL; + goto scfg_err; + } + + scfg_base = of_iomap(np, 0); + of_node_put(np); + if (!scfg_base) { + pr_err("%s: failed to map scfg.\n", __func__); + ret = -ENOMEM; + goto scfg_err; + } return 0; + +scfg_err: + iounmap(dcfg_base); +dcfg_err: + return ret; } -static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus) +void ls1021a_set_secondary_entry(void) { - struct device_node *np; - void __iomem *dcfg_base; unsigned long paddr; - np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); - dcfg_base = of_iomap(np, 0); - BUG_ON(!dcfg_base); +
[PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
From: Zhang Zhuoyu zhuoyu.zh...@freescale.com This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will always soft reset and boots up the same path as a cold boot. Signed-off-by: Zhang Zhuoyu zhuoyu.zh...@freescale.com --- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/hotplug.c | 25 + arch/arm/mach-imx/platsmp.c | 132 +++- arch/arm/mach-imx/src.c | 21 +++ 4 files changed, 169 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59ce8f3..f7d2be5 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -92,6 +92,7 @@ void imx_print_silicon_rev(const char *cpu, int srev); void imx_enable_cpu(int cpu, bool enable); void imx_set_cpu_jump(int cpu, void *jump_addr); u32 imx_get_cpu_arg(int cpu); +u32 ls1_get_cpu_arg(int cpu); void imx_set_cpu_arg(int cpu, u32 arg); #ifdef CONFIG_SMP void v7_secondary_startup(void); @@ -134,6 +135,9 @@ void imx6sl_pm_init(void); void imx6sx_pm_init(void); void imx6q_pm_set_ccm_base(void __iomem *base); +extern void ls1021a_cpu_die(unsigned int cpu); +extern int ls1021a_cpu_kill(unsigned int cpu); + #ifdef CONFIG_PM void imx51_pm_init(void); void imx53_pm_init(void); diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index b35e99c..2ee5e46 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -14,6 +14,7 @@ #include linux/jiffies.h #include asm/cp15.h #include asm/proc-fns.h +#include asm/cacheflush.h #include common.h @@ -68,3 +69,27 @@ int imx_cpu_kill(unsigned int cpu) imx_set_cpu_arg(cpu, 0); return 1; } + +/* + * For LS102x platforms, shutdowning a CPU is not supported by hardware. + * So we just put the offline CPU into lower-power state here. + */ +void __ref ls1021a_cpu_die(unsigned int cpu) +{ + v7_exit_coherency_flush(louis); + + /* LS1021a platform can't really power down a CPU, so we +* just put it into WFI state here. +*/ + wfi(); +} + +int ls1021a_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (!ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 7f27001..7735ebb 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -14,6 +14,7 @@ #include linux/of_address.h #include linux/of.h #include linux/smp.h +#include linux/delay.h #include asm/cacheflush.h #include asm/page.h @@ -23,8 +24,24 @@ #include common.h #include hardware.h +#defineSCFG_CORE0_SFT_RST 0x130 +#defineSCFG_REVCR 0x200 +#defineSCFG_CORESRENCR 0x204 +#defineSCFG_SPARECR4 0x50C + +#defineDCFG_CCSR_BRR 0x0E4 +#defineDCFG_CCSR_SCRATCHRW10x200 + +#defineDCSR_RCPM2_DEBUG1 0x400 +#defineDCSR_RCPM2_DEBUG2 0x414 + +#defineSTRIDE_4B 4 + u32 g_diag_reg; static void __iomem *scu_base; +static void __iomem *dcfg_base; +static void __iomem *scfg_base; +static u32 secondary_pre_boot_entry; static struct map_desc scu_io_desc __initdata = { /* .virtual and .pfn are run-time assigned */ @@ -98,32 +115,121 @@ struct smp_operations imx_smp_ops __initdata = { #endif }; -#define DCFG_CCSR_SCRATCHRW1 0x200 - -static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int ls1021a_secondary_iomap(void) { - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + struct device_node *np; + int ret; + + np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-dcfg); + if (!np) { + pr_err(%s: failed to find dcfg node.\n, __func__); + ret = -EINVAL; + goto dcfg_err; + } + + dcfg_base = of_iomap(np, 0); + of_node_put(np); + if (!dcfg_base) { + pr_err(%s: failed to map dcfg.\n, __func__); + ret = -ENOMEM; + goto dcfg_err; + } + + np = of_find_compatible_node(NULL, NULL, fsl,ls1021a-scfg); + if (!np) { + pr_err(%s: failed to find scfg node.\n, __func__); + ret = -EINVAL; + goto scfg_err; + } + + scfg_base = of_iomap(np, 0); + of_node_put(np); + if (!scfg_base) { + pr_err(%s: failed to map scfg.\n, __func__); + ret = -ENOMEM; + goto scfg_err; + } return 0; + +scfg_err: + iounmap(dcfg_base); +dcfg_err: + return ret; } -static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus) +void ls1021a_set_secondary_entry(void) { - struct device_node *np; - void __iomem *dcfg_base; unsigned long paddr;