* [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
@ 2014-11-24 5:28 Zhuoyu Zhang
2014-11-24 5:28 ` [PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset Zhuoyu Zhang
2014-11-28 10:33 ` [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Mark Rutland
0 siblings, 2 replies; 6+ messages in thread
From: Zhuoyu Zhang @ 2014-11-24 5:28 UTC (permalink / raw)
To: linux-arm-kernel
From: Zhang Zhuoyu <Zhuoyu.Zhang@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.Zhang@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"
+#define SCFG_CORE0_SFT_RST 0x130
+#define SCFG_REVCR 0x200
+#define SCFG_CORESRENCR 0x204
+#define SCFG_SPARECR4 0x50C
+
+#define DCFG_CCSR_BRR 0x0E4
+#define DCFG_CCSR_SCRATCHRW1 0x200
+
+#define DCSR_RCPM2_DEBUG1 0x400
+#define DCSR_RCPM2_DEBUG2 0x414
+
+#define STRIDE_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);
+ secondary_pre_boot_entry = readl_relaxed(dcfg_base +
+ DCFG_CCSR_SCRATCHRW1);
- paddr = virt_to_phys(secondary_startup);
- writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1);
+ if (dcfg_base) {
+ paddr = virt_to_phys(secondary_startup);
+ writel_relaxed(cpu_to_be32(paddr),
+ dcfg_base + DCFG_CCSR_SCRATCHRW1);
+ }
+}
- iounmap(dcfg_base);
+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(0xffffffff, scfg_base + SCFG_REVCR);
+
+ /* Soft reset secondary core */
+ iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
+ iowrite32be(0x80000000, 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;
+}
+
+static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
+{
+ ls1021a_secondary_iomap();
+ ls1021a_set_secondary_entry();
}
struct smp_operations ls1021a_smp_ops __initdata = {
.smp_prepare_cpus = ls1021a_smp_prepare_cpus,
.smp_boot_secondary = ls1021a_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = ls1021a_cpu_die,
+ .cpu_kill = ls1021a_cpu_kill,
+#endif
};
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 45f7f4e..7bd403a 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -30,6 +30,8 @@
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
+#define CCSR_TWAITSR0 0x04C
+
static void __iomem *src_base;
static DEFINE_SPINLOCK(scr_lock);
@@ -115,6 +117,25 @@ void imx_set_cpu_arg(int cpu, u32 arg)
writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
}
+u32 ls1_get_cpu_arg(int cpu)
+{
+ struct device_node *np;
+ void __iomem *ls1_rcpm_base;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.1");
+ if (!np) {
+ pr_err("%s(): Can not find the RCPM node.\n", __func__);
+ return -ENODEV;
+ }
+
+ ls1_rcpm_base = of_iomap(np, 0);
+ of_node_put(np);
+ WARN_ON(!ls1_rcpm_base);
+
+ cpu = cpu_logical_map(cpu);
+ return ioread32be(ls1_rcpm_base + CCSR_TWAITSR0) & (1 << cpu);
+}
+
void __init imx_src_init(void)
{
struct device_node *np;
--
2.1.0.27.g96db324
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset
2014-11-24 5:28 [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Zhuoyu Zhang
@ 2014-11-24 5:28 ` Zhuoyu Zhang
2014-11-28 10:33 ` [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Mark Rutland
1 sibling, 0 replies; 6+ messages in thread
From: Zhuoyu Zhang @ 2014-11-24 5:28 UTC (permalink / raw)
To: linux-arm-kernel
From: Zhang Zhuoyu <Zhuoyu.Zhang@freescale.com>
Due to a hardware erratum, after core soft reset, core state machine
registers need to force release manually.
Signed-off-by: Zhang Zhuoyu <Zhuoyu.Zhang@freescale.com>
---
arch/arm/mach-imx/platsmp.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 7735ebb..73c2289 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -41,6 +41,7 @@ u32 g_diag_reg;
static void __iomem *scu_base;
static void __iomem *dcfg_base;
static void __iomem *scfg_base;
+static void __iomem *dcsr_rcpm2_base;
static u32 secondary_pre_boot_entry;
static struct map_desc scu_io_desc __initdata = {
@@ -150,8 +151,25 @@ static int ls1021a_secondary_iomap(void)
goto scfg_err;
}
+ np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-rcpm");
+ if (!np) {
+ pr_err("%s: failed to find dcsr node.\n", __func__);
+ ret = -EINVAL;
+ goto dcsr_err;
+ }
+
+ dcsr_rcpm2_base = of_iomap(np, 1);
+ of_node_put(np);
+ if (!dcsr_rcpm2_base) {
+ pr_err("%s: failed to map dcsr.\n", __func__);
+ ret = -ENOMEM;
+ goto dcsr_err;
+ }
+
return 0;
+dcsr_err:
+ iounmap(scfg_base);
scfg_err:
iounmap(dcfg_base);
dcfg_err:
@@ -176,7 +194,7 @@ static int ls1021a_reset_secondary(unsigned int cpu)
{
u32 tmp;
- if (!scfg_base || !dcfg_base)
+ if (!scfg_base || !dcfg_base || !dcsr_rcpm2_base)
return -ENOMEM;
writel_relaxed(secondary_pre_boot_entry,
@@ -190,6 +208,15 @@ static int ls1021a_reset_secondary(unsigned int cpu)
iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
iowrite32be(0x80000000, scfg_base +
SCFG_CORE0_SFT_RST + STRIDE_4B * cpu);
+ mdelay(10);
+
+ /* LS1021a errata. after reset, core state machine registers
+ * need to force release manually.
+ */
+ iowrite32be(0x00000080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+ iowrite32be(0x00000080, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
+ iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG1);
+ iowrite32be(0, dcsr_rcpm2_base + DCSR_RCPM2_DEBUG2);
/* Release secondary core */
iowrite32be(1 << cpu, dcfg_base + DCFG_CCSR_BRR);
--
2.1.0.27.g96db324
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
2014-11-24 5:28 [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Zhuoyu Zhang
2014-11-24 5:28 ` [PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset Zhuoyu Zhang
@ 2014-11-28 10:33 ` Mark Rutland
2014-12-01 5:53 ` 答复: " Zhuoyu.Zhang at freescale.com
2014-12-01 8:40 ` Zhuoyu.Zhang at freescale.com
1 sibling, 2 replies; 6+ messages in thread
From: Mark Rutland @ 2014-11-28 10:33 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 24, 2014 at 05:28:09AM +0000, Zhuoyu Zhang wrote:
> From: Zhang Zhuoyu <Zhuoyu.Zhang@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.Zhang@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(0xffffffff, scfg_base + SCFG_REVCR);
> +
> + /* Soft reset secondary core */
> + iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
> + iowrite32be(0x80000000, 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.
^ permalink raw reply [flat|nested] 6+ messages in thread
* 答复: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
2014-11-28 10:33 ` [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Mark Rutland
@ 2014-12-01 5:53 ` Zhuoyu.Zhang at freescale.com
2014-12-01 10:18 ` Mark Rutland
2014-12-01 8:40 ` Zhuoyu.Zhang at freescale.com
1 sibling, 1 reply; 6+ messages in thread
From: Zhuoyu.Zhang at freescale.com @ 2014-12-01 5:53 UTC (permalink / raw)
To: linux-arm-kernel
> -----????-----
> ???: Mark Rutland [mailto:mark.rutland at arm.com]
> ????: Friday, November 28, 2014 6:33 PM
> ???: Zhang Zhuoyu-B46552
> ??: linux-kernel at vger.kernel.org; kernel at pengutronix.de; linux-arm-
> kernel at lists.infradead.org; Li Yang-Leo-R58472; linuxppc-
> release at linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336;
> linux at 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 +0000, Zhuoyu Zhang wrote:
> > From: Zhang Zhuoyu <Zhuoyu.Zhang@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.Zhang@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.
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(0xffffffff, scfg_base + SCFG_REVCR);
> > +
> > + /* Soft reset secondary core */
> > + iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
> > + iowrite32be(0x80000000, 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.
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
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
2014-11-28 10:33 ` [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Mark Rutland
2014-12-01 5:53 ` 答复: " Zhuoyu.Zhang at freescale.com
@ 2014-12-01 8:40 ` Zhuoyu.Zhang at freescale.com
1 sibling, 0 replies; 6+ messages in thread
From: Zhuoyu.Zhang at freescale.com @ 2014-12-01 8:40 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Mark Rutland [mailto:mark.rutland at arm.com]
> Sent: Friday, November 28, 2014 6:33 PM
> To: Zhang Zhuoyu-B46552
> Cc: linux-kernel at vger.kernel.org; kernel at pengutronix.de; linux-arm-
> kernel at lists.infradead.org; Li Yang-Leo-R58472; linuxppc-
> release at linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336;
> linux at 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 +0000, Zhuoyu Zhang wrote:
> > From: Zhang Zhuoyu <Zhuoyu.Zhang@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.Zhang@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(0xffffffff, scfg_base + SCFG_REVCR);
> > +
> > + /* Soft reset secondary core */
> > + iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
> > + iowrite32be(0x80000000, 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* 答复: [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support
2014-12-01 5:53 ` 答复: " Zhuoyu.Zhang at freescale.com
@ 2014-12-01 10:18 ` Mark Rutland
0 siblings, 0 replies; 6+ messages in thread
From: Mark Rutland @ 2014-12-01 10:18 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Dec 01, 2014 at 05:53:16AM +0000, Zhuoyu.Zhang at freescale.com wrote:
>
>
> > -----????-----
> > ???: Mark Rutland [mailto:mark.rutland at arm.com]
> > ????: Friday, November 28, 2014 6:33 PM
> > ???: Zhang Zhuoyu-B46552
> > ??: linux-kernel at vger.kernel.org; kernel at pengutronix.de; linux-arm-
> > kernel at lists.infradead.org; Li Yang-Leo-R58472; linuxppc-
> > release at linux.freescale.net; Jin Zhengxiong-R64188; Zhao Chenhui-B35336;
> > linux at 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 +0000, Zhuoyu Zhang wrote:
> > > From: Zhang Zhuoyu <Zhuoyu.Zhang@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.Zhang@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(0xffffffff, scfg_base + SCFG_REVCR);
> > > +
> > > + /* Soft reset secondary core */
> > > + iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
> > > + iowrite32be(0x80000000, 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.
>
>
> 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.
Thank you for the information. As described above I still do not believe
that this is sufficient.
Thanks,
Mark.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-12-01 10:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-24 5:28 [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Zhuoyu Zhang
2014-11-24 5:28 ` [PATCH v2 2/2] arm: ls1: provide a workaround for core soft reset Zhuoyu Zhang
2014-11-28 10:33 ` [PATCH v2 1/2] arm: ls1: add CPU hotplug platform support Mark Rutland
2014-12-01 5:53 ` 答复: " Zhuoyu.Zhang at freescale.com
2014-12-01 10:18 ` Mark Rutland
2014-12-01 8:40 ` Zhuoyu.Zhang at freescale.com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).