From: Soren Brinkmann <soren.brinkmann@xilinx.com> To: Michal Simek <michal.simek@xilinx.com>, Daniel Lezcano <daniel.lezcano@linaro.org> Cc: "Russell King" <linux@arm.linux.org.uk>, "Rafael J. Wysocki" <rjw@rjwysocki.net>, "Sören Brinkmann" <soren.brinkmann@xilinx.com>, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-pm@vger.kernel.org, "Rob Herring" <robh+dt@kernel.org>, "Mark Rutland" <mark.rutland@arm.com>, "Pawel Moll" <pawel.moll@arm.com>, "Ian Campbell" <ijc+devicetree@hellion.org.uk>, "Kumar Gala" <galak@codeaurora.org> Subject: [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Date: Tue, 2 Sep 2014 14:19:12 -0700 [thread overview] Message-ID: <1409692754-13437-8-git-send-email-soren.brinkmann@xilinx.com> (raw) In-Reply-To: <1409692754-13437-1-git-send-email-soren.brinkmann@xilinx.com> Avoid races and add synchronisation between the arch specific kill and die routines. The same synchronisation issue was fixed on IMX platform by this commit: "ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill" (sha1: 2f3edfd7e27ad4206acbc2ae99c9df5f46353024) Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> --- arch/arm/mach-zynq/common.h | 2 ++ arch/arm/mach-zynq/hotplug.c | 2 ++ arch/arm/mach-zynq/platsmp.c | 6 ++++++ arch/arm/mach-zynq/slcr.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 0edbb6997b1c..24d6340d3fb6 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -24,6 +24,8 @@ extern int zynq_early_slcr_init(void); extern void zynq_slcr_system_reset(void); extern void zynq_slcr_cpu_stop(int cpu); extern void zynq_slcr_cpu_start(int cpu); +extern bool zynq_slcr_cpu_state_read(int cpu); +extern void zynq_slcr_cpu_state_write(int cpu, bool die); extern u32 zynq_slcr_get_device_id(void); #ifdef CONFIG_SMP diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c index 366f46c91365..fe44a05677e2 100644 --- a/arch/arm/mach-zynq/hotplug.c +++ b/arch/arm/mach-zynq/hotplug.c @@ -19,6 +19,8 @@ */ void zynq_platform_cpu_die(unsigned int cpu) { + zynq_slcr_cpu_state_write(cpu, true); + /* * there is no power-control hardware on this platform, so all * we can do is put the core into WFI; this is safe as the calling diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c index 6c7843108c7f..06415eeba7e6 100644 --- a/arch/arm/mach-zynq/platsmp.c +++ b/arch/arm/mach-zynq/platsmp.c @@ -127,6 +127,12 @@ static void zynq_secondary_init(unsigned int cpu) #ifdef CONFIG_HOTPLUG_CPU static int zynq_cpu_kill(unsigned cpu) { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (zynq_slcr_cpu_state_read(cpu)) + if (time_after(jiffies, timeout)) + return 0; + zynq_slcr_cpu_stop(cpu); return 1; } diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index c43a2d16e223..d4cb50cf97c0 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -138,6 +138,8 @@ void zynq_slcr_cpu_start(int cpu) zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu); zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); + + zynq_slcr_cpu_state_write(cpu, false); } /** @@ -154,8 +156,47 @@ void zynq_slcr_cpu_stop(int cpu) } /** - * zynq_slcr_init - Regular slcr driver init + * zynq_slcr_cpu_state - Read/write cpu state + * @cpu: cpu number * + * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1) + * 0 means cpu is running, 1 cpu is going to die. + * + * Return: true if cpu is running, false if cpu is going to die + */ +bool zynq_slcr_cpu_state_read(int cpu) +{ + u32 state; + + state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); + state &= 1 << (31 - cpu); + + return !state; +} + +/** + * zynq_slcr_cpu_state - Read/write cpu state + * @cpu: cpu number + * @die: cpu state - true if cpu is going to die + * + * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1) + * 0 means cpu is running, 1 cpu is going to die. + */ +void zynq_slcr_cpu_state_write(int cpu, bool die) +{ + u32 state, mask; + + state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); + mask = 1 << (31 - cpu); + if (die) + state |= mask; + else + state &= ~mask; + writel(state, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); +} + +/** + * zynq_slcr_init - Regular slcr driver init * Return: 0 on success, negative errno otherwise. * * Called early during boot from platform code to remap SLCR area. -- 2.1.0.1.g27b9230
WARNING: multiple messages have this Message-ID (diff)
From: soren.brinkmann@xilinx.com (Soren Brinkmann) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Date: Tue, 2 Sep 2014 14:19:12 -0700 [thread overview] Message-ID: <1409692754-13437-8-git-send-email-soren.brinkmann@xilinx.com> (raw) In-Reply-To: <1409692754-13437-1-git-send-email-soren.brinkmann@xilinx.com> Avoid races and add synchronisation between the arch specific kill and die routines. The same synchronisation issue was fixed on IMX platform by this commit: "ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill" (sha1: 2f3edfd7e27ad4206acbc2ae99c9df5f46353024) Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> --- arch/arm/mach-zynq/common.h | 2 ++ arch/arm/mach-zynq/hotplug.c | 2 ++ arch/arm/mach-zynq/platsmp.c | 6 ++++++ arch/arm/mach-zynq/slcr.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 0edbb6997b1c..24d6340d3fb6 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -24,6 +24,8 @@ extern int zynq_early_slcr_init(void); extern void zynq_slcr_system_reset(void); extern void zynq_slcr_cpu_stop(int cpu); extern void zynq_slcr_cpu_start(int cpu); +extern bool zynq_slcr_cpu_state_read(int cpu); +extern void zynq_slcr_cpu_state_write(int cpu, bool die); extern u32 zynq_slcr_get_device_id(void); #ifdef CONFIG_SMP diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c index 366f46c91365..fe44a05677e2 100644 --- a/arch/arm/mach-zynq/hotplug.c +++ b/arch/arm/mach-zynq/hotplug.c @@ -19,6 +19,8 @@ */ void zynq_platform_cpu_die(unsigned int cpu) { + zynq_slcr_cpu_state_write(cpu, true); + /* * there is no power-control hardware on this platform, so all * we can do is put the core into WFI; this is safe as the calling diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c index 6c7843108c7f..06415eeba7e6 100644 --- a/arch/arm/mach-zynq/platsmp.c +++ b/arch/arm/mach-zynq/platsmp.c @@ -127,6 +127,12 @@ static void zynq_secondary_init(unsigned int cpu) #ifdef CONFIG_HOTPLUG_CPU static int zynq_cpu_kill(unsigned cpu) { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (zynq_slcr_cpu_state_read(cpu)) + if (time_after(jiffies, timeout)) + return 0; + zynq_slcr_cpu_stop(cpu); return 1; } diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index c43a2d16e223..d4cb50cf97c0 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -138,6 +138,8 @@ void zynq_slcr_cpu_start(int cpu) zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu); zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); + + zynq_slcr_cpu_state_write(cpu, false); } /** @@ -154,8 +156,47 @@ void zynq_slcr_cpu_stop(int cpu) } /** - * zynq_slcr_init - Regular slcr driver init + * zynq_slcr_cpu_state - Read/write cpu state + * @cpu: cpu number * + * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1) + * 0 means cpu is running, 1 cpu is going to die. + * + * Return: true if cpu is running, false if cpu is going to die + */ +bool zynq_slcr_cpu_state_read(int cpu) +{ + u32 state; + + state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); + state &= 1 << (31 - cpu); + + return !state; +} + +/** + * zynq_slcr_cpu_state - Read/write cpu state + * @cpu: cpu number + * @die: cpu state - true if cpu is going to die + * + * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1) + * 0 means cpu is running, 1 cpu is going to die. + */ +void zynq_slcr_cpu_state_write(int cpu, bool die) +{ + u32 state, mask; + + state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); + mask = 1 << (31 - cpu); + if (die) + state |= mask; + else + state &= ~mask; + writel(state, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); +} + +/** + * zynq_slcr_init - Regular slcr driver init * Return: 0 on success, negative errno otherwise. * * Called early during boot from platform code to remap SLCR area. -- 2.1.0.1.g27b9230
next prev parent reply other threads:[~2014-09-02 21:19 UTC|newest] Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top 2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 2/9] Documentation: devicetree: Add binding for Synopsys DDR controller Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-03 13:49 ` Daniel Lezcano 2014-09-03 13:49 ` Daniel Lezcano 2014-09-02 21:19 ` [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-04 12:16 ` Daniel Lezcano 2014-09-04 12:16 ` Daniel Lezcano 2014-09-04 12:16 ` Daniel Lezcano 2014-09-02 21:19 ` [PATCH v2 5/9] ARM: zynq: Remove invalidate cache for cpu die Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 6/9] ARM: zynq: cpuidle: Remove pointless code Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann [this message] 2014-09-02 21:19 ` [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 8/9] ARM: zynq: Remove hotplug.c Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-02 21:19 ` [PATCH v2 9/9] ARM: zynq: Rename 'zynq_platform_cpu_die' Soren Brinkmann 2014-09-02 21:19 ` Soren Brinkmann 2014-09-15 13:34 ` [PATCH v2 0/9] Zynq PM updates Michal Simek 2014-09-15 13:34 ` Michal Simek 2014-09-15 13:34 ` Michal Simek
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1409692754-13437-8-git-send-email-soren.brinkmann@xilinx.com \ --to=soren.brinkmann@xilinx.com \ --cc=daniel.lezcano@linaro.org \ --cc=devicetree@vger.kernel.org \ --cc=galak@codeaurora.org \ --cc=ijc+devicetree@hellion.org.uk \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-pm@vger.kernel.org \ --cc=linux@arm.linux.org.uk \ --cc=mark.rutland@arm.com \ --cc=michal.simek@xilinx.com \ --cc=pawel.moll@arm.com \ --cc=rjw@rjwysocki.net \ --cc=robh+dt@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.