From: Tang Yuantian <yuantian.t...@freescale.com> Freescale E500MC and E5500 core-based platforms, like P4080, T1040, support disabling/enabling CPU dynamically. This patch adds this feature on those platforms.
Signed-off-by: Chenhui Zhao <chenhui.z...@freescale.com> Signed-off-by: Tang Yuantian <yuantian.t...@feescale.com> --- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/smp.h | 1 + arch/powerpc/kernel/smp.c | 5 +++++ arch/powerpc/platforms/85xx/smp.c | 39 ++++++++++++++++++++++++++++++++------- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5ef2711..dd9e252 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -386,7 +386,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/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 825663c..bf37d17 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -67,6 +67,7 @@ void generic_cpu_die(unsigned int cpu); void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_up(unsigned int cpu); int generic_check_cpu_restart(unsigned int cpu); +int generic_check_cpu_dead(unsigned int cpu); #endif #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ec9ec20..2cca27a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -454,6 +454,11 @@ int generic_check_cpu_restart(unsigned int cpu) return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; } +int generic_check_cpu_dead(unsigned int cpu) +{ + return per_cpu(cpu_state, cpu) == CPU_DEAD; +} + static bool secondaries_inhibited(void) { return kvm_hv_mode_active(); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 6811a5b..7f0dadb 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -42,6 +42,7 @@ struct epapr_spin_table { u32 pir; }; +#ifdef CONFIG_HOTPLUG_CPU static u64 timebase; static int tb_req; static int tb_valid; @@ -111,7 +112,7 @@ static void mpc85xx_take_timebase(void) local_irq_restore(flags); } -#ifdef CONFIG_HOTPLUG_CPU +#ifndef CONFIG_PPC_E500MC static void e500_cpu_idle(void) { u32 tmp; @@ -127,6 +128,7 @@ static void e500_cpu_idle(void) mtmsr(tmp); isync(); } +#endif static void qoriq_cpu_dying(void) { @@ -144,11 +146,30 @@ static void qoriq_cpu_dying(void) generic_set_cpu_dead(cpu); +#ifndef CONFIG_PPC_E500MC e500_cpu_idle(); +#endif while (1) ; } + +static void qoriq_real_cpu_die(unsigned int cpu) +{ + int i; + + for (i = 0; i < 50000; i++) { + if (generic_check_cpu_dead(cpu)) { + qoriq_pm_ops->cpu_die(cpu); +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif + return; + } + udelay(10); + } + pr_err("%s: CPU%d didn't die...\n", __func__, cpu); +} #endif static inline void flush_spin_table(void *spin_table) @@ -246,11 +267,7 @@ 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); - if (system_state == SYSTEM_RUNNING) { /* * To keep it compatible with old boot program which uses @@ -263,6 +280,7 @@ static int smp_85xx_kick_cpu(int nr) out_be32(&spin_table->addr_l, 0); flush_spin_table(spin_table); + qoriq_pm_ops->cpu_up(nr); /* * We don't set the BPTR register here since it already points * to the boot page properly. @@ -286,7 +304,12 @@ static int smp_85xx_kick_cpu(int nr) /* clear the acknowledge status */ __secondary_hold_acknowledge = -1; } + + /* Corresponding to generic_set_cpu_dead() */ + generic_set_cpu_up(nr); #endif + +#ifdef CONFIG_PPC32 flush_spin_table(spin_table); out_be32(&spin_table->pir, hw_cpu); out_be32(&spin_table->addr_l, __pa(__early_start)); @@ -300,7 +323,6 @@ static int smp_85xx_kick_cpu(int nr) ret = -ENOENT; goto out; } -out: #else smp_generic_kick_cpu(nr); @@ -311,6 +333,9 @@ out: flush_spin_table(spin_table); #endif +#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PPC32) +out: +#endif local_irq_restore(flags); if (ioremappable) @@ -324,7 +349,7 @@ struct smp_ops_t smp_85xx_ops = { .cpu_bootable = smp_generic_cpu_bootable, #ifdef CONFIG_HOTPLUG_CPU .cpu_disable = generic_cpu_disable, - .cpu_die = generic_cpu_die, + .cpu_die = qoriq_real_cpu_die, #endif #if defined(CONFIG_KEXEC) || defined(CONFIG_HOTPLUG_CPU) .give_timebase = mpc85xx_give_timebase, -- 2.1.0.27.g96db324 -- 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/