From patchwork Sat Apr 30 02:08:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 742972 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3U28ljo027707 for ; Sat, 30 Apr 2011 02:09:04 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759591Ab1D3CIv (ORCPT ); Fri, 29 Apr 2011 22:08:51 -0400 Received: from mail-gw0-f46.google.com ([74.125.83.46]:55615 "EHLO mail-gw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755809Ab1D3CIu (ORCPT ); Fri, 29 Apr 2011 22:08:50 -0400 Received: by gwaa18 with SMTP id a18so1492059gwa.19 for ; Fri, 29 Apr 2011 19:08:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=sMOhL46TWhbb0PesWNeJo0o9+d2dScFVGbcH7Z/4xMo=; b=Q6C1M/qQe7/WcWoAlhkmH2RmBZtFAyR+m8e/0dmNTCZx+7UE8HbMYmTXiXhMdIfsb1 EEIpsifRysAbTvV+an6RIHiD/BqJTqw1FamoppOOlkecYA4KaKV54q1JdblmDyc4dbE6 t32k7MTgBuxNgtPyDvawkR2PbSTGR8i/AubCA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=V9suQ3SLF9brgWLMWM4/mbqusEqo4Oz3+p0M+wut7oQWd3a+8M6dWIcKVNo3GwtqgJ 4dl19qmR0rwczbc80ivkDBGXIesLgzBujd+zzv5DVEM548xWB9K62h5MDbhVVXPmAeyc vupzTHP7VpOlqgY0WklAZdZgL0NDB8SVRMeZQ= Received: by 10.90.153.2 with SMTP id a2mr2377235age.36.1304129329308; Fri, 29 Apr 2011 19:08:49 -0700 (PDT) Received: from rob-laptop.grandecom.net (65-36-74-215.dyn.grandenetworks.net [65.36.74.215]) by mx.google.com with ESMTPS id w6sm3345086anf.32.2011.04.29.19.08.47 (version=SSLv3 cipher=OTHER); Fri, 29 Apr 2011 19:08:48 -0700 (PDT) From: Rob Herring To: linux-arm-msm@vger.kernel.org, linux-sh@vger.kernel.org, Srinidhi Kasagar , Linus Walleij , Russell King , David Brown , Daniel Walker , Paul Mundt , linux-arm-kernel@lists.infradead.org Cc: Rob Herring Subject: [PATCH 01/10] ARM: move Versatile SMP pen code to common location Date: Fri, 29 Apr 2011 21:08:08 -0500 Message-Id: <1304129297-6614-2-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1304129297-6614-1-git-send-email-robherring2@gmail.com> References: <1304129297-6614-1-git-send-email-robherring2@gmail.com> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sat, 30 Apr 2011 02:09:05 +0000 (UTC) From: Rob Herring The same secondary boot pen code is used by several platforms besides ARM Ltd boards, so move it to a shared location. Signed-off-by: Rob Herring --- arch/arm/Kconfig | 7 ++ arch/arm/include/asm/smp.h | 4 + arch/arm/kernel/Makefile | 3 +- arch/arm/kernel/headsmp.S | 40 +++++++++++ arch/arm/kernel/smp_pen.c | 104 +++++++++++++++++++++++++++++ arch/arm/mach-realview/include/mach/smp.h | 3 + arch/arm/mach-realview/platsmp.c | 4 +- arch/arm/mach-vexpress/include/mach/smp.h | 3 + arch/arm/mach-vexpress/platsmp.c | 4 +- arch/arm/plat-versatile/Makefile | 1 - arch/arm/plat-versatile/headsmp.S | 40 ----------- arch/arm/plat-versatile/platsmp.c | 104 ----------------------------- 12 files changed, 165 insertions(+), 152 deletions(-) create mode 100644 arch/arm/kernel/headsmp.S create mode 100644 arch/arm/kernel/smp_pen.c delete mode 100644 arch/arm/plat-versatile/headsmp.S delete mode 100644 arch/arm/plat-versatile/platsmp.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d46185a..84e2127 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1057,6 +1057,7 @@ config PLAT_PXA config PLAT_VERSATILE bool + select SMP_COMMON_PEN if SMP config ARM_TIMER_SP804 bool @@ -1381,6 +1382,12 @@ config HAVE_ARM_SCU help This option enables support for the ARM system coherency unit +config SMP_COMMON_PEN + bool + depends on SMP + help + This option enables common secondary boot pen code. + config HAVE_ARM_TWD bool depends on SMP diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 96ed521..6766cd3 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -73,6 +73,10 @@ extern void platform_secondary_init(unsigned int cpu); */ extern void platform_smp_prepare_cpus(unsigned int); +extern void pen_secondary_init(unsigned int cpu); +extern int pen_boot_secondary(unsigned int cpu, struct task_struct *); +extern void pen_secondary_startup(void); + /* * Initial data for bringing up a secondary CPU. */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 908c78c..62061fa 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_OC_ETM) += etm.o obj-$(CONFIG_ISA_DMA_API) += dma.o -obj-$(CONFIG_ARCH_ACORN) += ecard.o +obj-$(CONFIG_ARCH_ACORN) += ecard.o obj-$(CONFIG_FIQ) += fiq.o obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o @@ -32,6 +32,7 @@ obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_PM_SLEEP) += sleep.o obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o +obj-$(CONFIG_SMP_COMMON_PEN) += headsmp.o smp_pen.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o diff --git a/arch/arm/kernel/headsmp.S b/arch/arm/kernel/headsmp.S new file mode 100644 index 0000000..712b401 --- /dev/null +++ b/arch/arm/kernel/headsmp.S @@ -0,0 +1,40 @@ +/* + * linux/arch/arm/kernel/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + + __INIT + +/* + * Entry point for secondary CPUs. + * This provides a "holding pen" into which all secondary cores are held + * until we're ready for them to initialise. + */ +ENTRY(pen_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + + .align +1: .long . + .long pen_release diff --git a/arch/arm/kernel/smp_pen.c b/arch/arm/kernel/smp_pen.c new file mode 100644 index 0000000..8a81eeb --- /dev/null +++ b/arch/arm/kernel/smp_pen.c @@ -0,0 +1,104 @@ +/* + * linux/arch/arm/kernel/smp_pen.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + +/* + * Write pen_release in a way that is guaranteed to be visible to all + * observers, irrespective of whether they're taking part in coherency + * or not. This is necessary for the hotplug code to work reliably. + */ +static void __cpuinit write_pen_release(int val) +{ + pen_release = val; + smp_wmb(); + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit pen_secondary_init(unsigned int cpu) +{ + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_secondary_init(0); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit pen_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + smp_cross_call(cpumask_of(cpu), 1); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index c8221b3..e688f64 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h @@ -3,6 +3,9 @@ #include +#define boot_secondary pen_boot_secondary +#define platform_secondary_init pen_secondary_init + /* * We use IRQ1 as the IPI */ diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 2391922..f443ef3 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -24,8 +24,6 @@ #include "core.h" -extern void versatile_secondary_startup(void); - static void __iomem *scu_base_addr(void) { if (machine_is_realview_eb_mp()) @@ -82,6 +80,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) * until it receives a soft interrupt, and then the * secondary CPU branches to this address. */ - __raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)), + __raw_writel(BSYM(virt_to_phys(pen_secondary_startup)), __io_address(REALVIEW_SYS_FLAGSSET)); } diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h index 4c05e4a..306ff05 100644 --- a/arch/arm/mach-vexpress/include/mach/smp.h +++ b/arch/arm/mach-vexpress/include/mach/smp.h @@ -3,6 +3,9 @@ #include +#define boot_secondary pen_boot_secondary +#define platform_secondary_init pen_secondary_init + /* * We use IRQ1 as the IPI */ diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 2b5f7ac..7fa0b68 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -20,8 +20,6 @@ #include "core.h" -extern void versatile_secondary_startup(void); - /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. @@ -46,6 +44,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) * secondary CPU branches to this address. */ writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); - writel(BSYM(virt_to_phys(versatile_secondary_startup)), + writel(BSYM(virt_to_phys(pen_secondary_startup)), MMIO_P2V(V2M_SYS_FLAGSSET)); } diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 86fe64d..ef7b749 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -3,4 +3,3 @@ obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o -obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S deleted file mode 100644 index d397a1f..0000000 --- a/arch/arm/plat-versatile/headsmp.S +++ /dev/null @@ -1,40 +0,0 @@ -/* - * linux/arch/arm/plat-versatile/headsmp.S - * - * Copyright (c) 2003 ARM Limited - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include - - __INIT - -/* - * Realview/Versatile Express specific entry point for secondary CPUs. - * This provides a "holding pen" into which all secondary cores are held - * until we're ready for them to initialise. - */ -ENTRY(versatile_secondary_startup) - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - adr r4, 1f - ldmia r4, {r5, r6} - sub r4, r4, r5 - add r6, r6, r4 -pen: ldr r7, [r6] - cmp r7, r0 - bne pen - - /* - * we've been released from the holding pen: secondary_stack - * should now contain the SVC stack for this core - */ - b secondary_startup - - .align -1: .long . - .long pen_release diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c deleted file mode 100644 index ba3d471..0000000 --- a/arch/arm/plat-versatile/platsmp.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * linux/arch/arm/plat-versatile/platsmp.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include - -#include - -/* - * control for which core is the next to come out of the secondary - * boot "holding pen" - */ -volatile int __cpuinitdata pen_release = -1; - -/* - * Write pen_release in a way that is guaranteed to be visible to all - * observers, irrespective of whether they're taking part in coherency - * or not. This is necessary for the hotplug code to work reliably. - */ -static void __cpuinit write_pen_release(int val) -{ - pen_release = val; - smp_wmb(); - __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); - outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); -} - -static DEFINE_SPINLOCK(boot_lock); - -void __cpuinit platform_secondary_init(unsigned int cpu) -{ - /* - * if any interrupts are already enabled for the primary - * core (e.g. timer irq), then they will not have been enabled - * for us: do so - */ - gic_secondary_init(0); - - /* - * let the primary processor know we're out of the - * pen, then head off into the C entry point - */ - write_pen_release(-1); - - /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); -} - -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - unsigned long timeout; - - /* - * Set synchronisation state between this boot processor - * and the secondary one - */ - spin_lock(&boot_lock); - - /* - * This is really belt and braces; we hold unintended secondary - * CPUs in the holding pen until we're ready for them. However, - * since we haven't sent them a soft interrupt, they shouldn't - * be there. - */ - write_pen_release(cpu); - - /* - * Send the secondary CPU a soft interrupt, thereby causing - * the boot monitor to read the system wide flags register, - * and branch to the address found there. - */ - smp_cross_call(cpumask_of(cpu), 1); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - smp_rmb(); - if (pen_release == -1) - break; - - udelay(10); - } - - /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - spin_unlock(&boot_lock); - - return pen_release != -1 ? -ENOSYS : 0; -}