From patchwork Fri Mar 7 04:58:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: chenhui zhao X-Patchwork-Id: 327799 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id D1B3D2C0607 for ; Fri, 7 Mar 2014 16:00:26 +1100 (EST) Received: from va3outboundpool.messaging.microsoft.com (va3ehsobe004.messaging.microsoft.com [216.32.180.14]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 9B3642C0358 for ; Fri, 7 Mar 2014 15:58:34 +1100 (EST) Received: from mail232-va3-R.bigfish.com (10.7.14.246) by VA3EHSOBE008.bigfish.com (10.7.40.28) with Microsoft SMTP Server id 14.1.225.22; Fri, 7 Mar 2014 04:58:30 +0000 Received: from mail232-va3 (localhost [127.0.0.1]) by mail232-va3-R.bigfish.com (Postfix) with ESMTP id 231EE5C04B5; Fri, 7 Mar 2014 04:58:30 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1f42h2148h208ch1ee6h1de0h1fdah2073h2146h1202h1e76h2189h1d1ah1d2ah21bch1fc6hzz1de098h8275bh1de097hz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h1354h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh2222h224fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h24afh2327h2336h2438h2461h2487h24d7h2516h2545h255eh25cch25f6h2605h1155h) Received: from mail232-va3 (localhost.localdomain [127.0.0.1]) by mail232-va3 (MessageSwitch) id 1394168307652951_15605; Fri, 7 Mar 2014 04:58:27 +0000 (UTC) Received: from VA3EHSMHS040.bigfish.com (unknown [10.7.14.226]) by mail232-va3.bigfish.com (Postfix) with ESMTP id 9A4B6B0004C; Fri, 7 Mar 2014 04:58:27 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS040.bigfish.com (10.7.99.50) with Microsoft SMTP Server (TLS) id 14.16.227.3; Fri, 7 Mar 2014 04:58:27 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.3.158.2; Fri, 7 Mar 2014 04:58:25 +0000 Received: from localhost.localdomain ([10.193.20.174]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id s274w9Dv005153; Thu, 6 Mar 2014 21:58:23 -0700 From: Chenhui Zhao To: Subject: [PATCH 4/9] powerpc/85xx: support CPU hotplug for e500mc and e5500 Date: Fri, 7 Mar 2014 12:58:00 +0800 Message-ID: <1394168285-32275-4-git-send-email-chenhui.zhao@freescale.com> X-Mailer: git-send-email 1.7.3 In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com> References: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-FOPE-CONNECTOR: Id%0$Dn%FREESCALE.MAIL.ONMICROSOFT.COM$RO%1$TLS%0$FQDN%$TlsDn% Cc: scottwood@freescale.com, linux-kernel@vger.kernel.org, Jason.Jin@freescale.com X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Implemented CPU hotplug on e500mc and e5500. On e5500 both 32-bit and 64-bit modes can work. Used some callback functions implemented in RCPM driver. Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/smp.c | 6 ++- arch/powerpc/mm/tlb_nohash.c | 6 ++- arch/powerpc/platforms/85xx/smp.c | 94 ++++++++++++++++++++++++++++++------- 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a5e5d2e..05f6323 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -362,7 +362,7 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ - PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) + PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE) ---help--- Say Y here to be able to disable and re-enable individual CPUs at runtime on SMP machines. diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ac2621a..f3f4401 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -405,8 +405,12 @@ void generic_cpu_die(unsigned int cpu) for (i = 0; i < 100; i++) { smp_rmb(); - if (per_cpu(cpu_state, cpu) == CPU_DEAD) + if (per_cpu(cpu_state, cpu) == CPU_DEAD) { +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif return; + } msleep(100); } printk(KERN_ERR "CPU%d didn't die...\n", cpu); diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index b37a58e..d24e06c 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -648,8 +648,10 @@ static void __early_init_mmu(int boot_cpu) num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; linear_map_top = map_mem_in_cams(linear_map_top, num_cams); - /* limit memory so we dont have linear faults */ - memblock_enforce_memory_limit(linear_map_top); + if (boot_cpu) { + /* limit memory so we dont have linear faults */ + memblock_enforce_memory_limit(linear_map_top); + } if (book3e_htw_mode == PPC_HTW_NONE) { patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 2e5911e..0047883 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,17 @@ static u64 timebase; static int tb_req; static int tb_valid; +#ifdef CONFIG_PPC_E500MC +/* specify the cpu PM state when cpu dies, PH15/NAP is the default */ +int qoriq_cpu_die_state = E500_PM_PH15; +#endif + +#ifdef CONFIG_PPC_E500MC +static void mpc85xx_timebase_freeze(int freeze) +{ + qoriq_pm_ops->freeze_time_base(freeze); +} +#else static void mpc85xx_timebase_freeze(int freeze) { uint32_t mask; @@ -58,6 +70,7 @@ static void mpc85xx_timebase_freeze(int freeze) in_be32(&guts->devdisr); } +#endif static void mpc85xx_give_timebase(void) { @@ -125,6 +138,34 @@ static void mpc85xx_take_timebase(void) } #ifdef CONFIG_HOTPLUG_CPU +#ifdef CONFIG_PPC_E500MC +static void qoriq_cpu_die(void) +{ + unsigned int cpu = smp_processor_id(); + + local_irq_disable(); +#ifdef CONFIG_PPC64 + __hard_irq_disable(); +#endif + idle_task_exit(); + + if (qoriq_pm_ops->irq_mask) + qoriq_pm_ops->irq_mask(cpu); + + mtspr(SPRN_TCR, 0); + mtspr(SPRN_TSR, mfspr(SPRN_TSR)); + + generic_set_cpu_dead(cpu); + + if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches) + cur_cpu_spec->cpu_flush_caches(); + + qoriq_pm_ops->cpu_enter_state(cpu, qoriq_cpu_die_state); + + while (1) + ; +} +#else static void smp_85xx_mach_cpu_die(void) { unsigned int cpu = smp_processor_id(); @@ -155,6 +196,7 @@ static void smp_85xx_mach_cpu_die(void) ; } #endif +#endif static inline void flush_spin_table(void *spin_table) { @@ -208,11 +250,8 @@ static int smp_85xx_kick_cpu(int nr) spin_table = phys_to_virt(*cpu_rel_addr); local_irq_save(flags); -#ifdef CONFIG_PPC32 -#ifdef CONFIG_HOTPLUG_CPU - /* Corresponding to generic_set_cpu_dead() */ - generic_set_cpu_up(nr); +#ifdef CONFIG_HOTPLUG_CPU if (system_state == SYSTEM_RUNNING) { /* * To keep it compatible with old boot program which uses @@ -225,6 +264,12 @@ static int smp_85xx_kick_cpu(int nr) out_be32(&spin_table->addr_l, 0); flush_spin_table(spin_table); +#ifdef CONFIG_PPC_E500MC + /* Due to an erratum, wake the core before reset. */ + if (qoriq_pm_ops && qoriq_pm_ops->cpu_exit_state) + qoriq_pm_ops->cpu_exit_state(nr, qoriq_cpu_die_state); +#endif + /* * We don't set the BPTR register here since it already points * to the boot page properly. @@ -247,13 +292,30 @@ static int smp_85xx_kick_cpu(int nr) /* clear the acknowledge status */ __secondary_hold_acknowledge = -1; + +#ifdef CONFIG_PPC_E500MC + if (qoriq_pm_ops->irq_unmask) + qoriq_pm_ops->irq_unmask(nr); +#endif } + + /* Corresponding to generic_set_cpu_dead() */ + generic_set_cpu_up(nr); #endif + flush_spin_table(spin_table); out_be32(&spin_table->pir, hw_cpu); +#ifdef CONFIG_PPC32 out_be32(&spin_table->addr_l, __pa(__early_start)); +#else + out_be32(&spin_table->addr_h, + __pa(*(u64 *)generic_secondary_smp_init) >> 32); + out_be32(&spin_table->addr_l, + __pa(*(u64 *)generic_secondary_smp_init) & 0xffffffff); +#endif flush_spin_table(spin_table); +#ifdef CONFIG_PPC32 /* Wait a bit for the CPU to ack. */ if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu, 10000, 100)) { @@ -262,17 +324,10 @@ static int smp_85xx_kick_cpu(int nr) ret = -ENOENT; goto out; } -out: #else smp_generic_kick_cpu(nr); - - flush_spin_table(spin_table); - out_be32(&spin_table->pir, hw_cpu); - out_be64((u64 *)(&spin_table->addr_h), - __pa((u64)*((unsigned long long *)generic_secondary_smp_init))); - flush_spin_table(spin_table); #endif - +out: local_irq_restore(flags); if (ioremappable) @@ -445,13 +500,18 @@ void __init mpc85xx_smp_init(void) __func__); return; } - smp_85xx_ops.give_timebase = mpc85xx_give_timebase; - smp_85xx_ops.take_timebase = mpc85xx_take_timebase; -#ifdef CONFIG_HOTPLUG_CPU - ppc_md.cpu_die = smp_85xx_mach_cpu_die; -#endif } + smp_85xx_ops.give_timebase = mpc85xx_give_timebase; + smp_85xx_ops.take_timebase = mpc85xx_take_timebase; + +#ifdef CONFIG_HOTPLUG_CPU +#ifdef CONFIG_PPC_E500MC + ppc_md.cpu_die = qoriq_cpu_die; +#else + ppc_md.cpu_die = smp_85xx_mach_cpu_die; +#endif +#endif smp_ops = &smp_85xx_ops; #ifdef CONFIG_KEXEC