Re: 答复: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support

2014-12-01 Thread Mark Rutland
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

2014-12-01 Thread zhuoyu.zh...@freescale.com


> -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

2014-12-01 Thread zhuoyu.zh...@freescale.com


 -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

2014-12-01 Thread Mark Rutland
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

2014-11-28 Thread Mark Rutland
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

2014-11-28 Thread Mark Rutland
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

2014-11-23 Thread Zhuoyu Zhang
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

2014-11-23 Thread Zhuoyu Zhang
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;