From ae5cab476342bc7311945cf89d5cbd8d57f4a5a9 Mon Sep 17 00:00:00 2001 From: Zhao Chenhui Date: Fri, 20 Jul 2012 20:42:34 +0800 Subject: powerpc/smp: add generic_set_cpu_up() to set cpu_state as CPU_UP_PREPARE In the case of cpu hotplug, the cpu_state should be set to CPU_UP_PREPARE when kicking cpu. Otherwise, the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(), which makes the delay in generic_cpu_die() not happen. Signed-off-by: Zhao Chenhui Signed-off-by: Kumar Gala --- arch/powerpc/kernel/smp.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8d4214afc21d..a51ed205016e 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -102,7 +102,7 @@ int __devinit smp_generic_kick_cpu(int nr) * Ok it's not there, so it might be soft-unplugged, let's * try to bring it back */ - per_cpu(cpu_state, nr) = CPU_UP_PREPARE; + generic_set_cpu_up(nr); smp_wmb(); smp_send_reschedule(nr); #endif /* CONFIG_HOTPLUG_CPU */ @@ -413,6 +413,16 @@ void generic_set_cpu_dead(unsigned int cpu) per_cpu(cpu_state, cpu) = CPU_DEAD; } +/* + * The cpu_state should be set to CPU_UP_PREPARE in kick_cpu(), otherwise + * the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(), + * which makes the delay in generic_cpu_die() not happen. + */ +void generic_set_cpu_up(unsigned int cpu) +{ + per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; +} + int generic_check_cpu_restart(unsigned int cpu) { return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; -- cgit v1.2.3 From d0832a75075b1119635e0f48549e378040cf5e67 Mon Sep 17 00:00:00 2001 From: Zhao Chenhui Date: Fri, 20 Jul 2012 20:42:36 +0800 Subject: powerpc/85xx: add HOTPLUG_CPU support Add support to disable and re-enable individual cores at runtime on MPC85xx/QorIQ SMP machines. Currently support e500v1/e500v2 core. MPC85xx machines use ePAPR spin-table in boot page for CPU kick-off. This patch uses the boot page from bootloader to boot core at runtime. It supports 32-bit and 36-bit physical address. Signed-off-by: Li Yang Signed-off-by: Jin Qing Signed-off-by: Zhao Chenhui Signed-off-by: Kumar Gala --- arch/powerpc/Kconfig | 6 ++- arch/powerpc/include/asm/cacheflush.h | 2 + arch/powerpc/include/asm/smp.h | 1 + arch/powerpc/kernel/head_fsl_booke.S | 28 +++++++++++ arch/powerpc/platforms/85xx/smp.c | 90 ++++++++++++++++++++++++++++++----- 5 files changed, 112 insertions(+), 15 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 98e513b62709..b8bab10bd0f1 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -215,7 +215,8 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ - (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x + (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ + || 44x || 40x config PPC_DCR_NATIVE bool @@ -328,7 +329,8 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" - depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV) + depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || \ + PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) ---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/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index ab9e402518e8..b843e35122e8 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -30,6 +30,8 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) +extern void __flush_disable_L1(void); + extern void __flush_icache_range(unsigned long, unsigned long); static inline void flush_icache_range(unsigned long start, unsigned long stop) { diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index ce8e2bdf84ed..e807e9d8e3f7 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -191,6 +191,7 @@ extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; extern char __secondary_hold; +extern void __early_start(void); #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 0f59863c3ade..b221541d9861 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -1043,6 +1043,34 @@ _GLOBAL(flush_dcache_L1) blr +/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */ +_GLOBAL(__flush_disable_L1) + mflr r10 + bl flush_dcache_L1 /* Flush L1 d-cache */ + mtlr r10 + + mfspr r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */ + li r5, 2 + rlwimi r4, r5, 0, 3 + + msync + isync + mtspr SPRN_L1CSR0, r4 + isync + +1: mfspr r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */ + andi. r4, r4, 2 + bne 1b + + mfspr r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */ + li r5, 2 + rlwimi r4, r5, 0, 3 + + mtspr SPRN_L1CSR1, r4 + isync + + blr + #ifdef CONFIG_SMP /* When we get here, r24 needs to hold the CPU # */ .globl __secondary_start diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 7ed52a604a13..6fcfa12e5c56 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -31,8 +31,6 @@ #include #include "smp.h" -extern void __early_start(void); - struct epapr_spin_table { u32 addr_h; u32 addr_l; @@ -100,15 +98,45 @@ static void mpc85xx_take_timebase(void) local_irq_restore(flags); } -static int __init -smp_85xx_kick_cpu(int nr) +#ifdef CONFIG_HOTPLUG_CPU +static void __cpuinit smp_85xx_mach_cpu_die(void) +{ + unsigned int cpu = smp_processor_id(); + u32 tmp; + + local_irq_disable(); + idle_task_exit(); + generic_set_cpu_dead(cpu); + mb(); + + mtspr(SPRN_TCR, 0); + + __flush_disable_L1(); + tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP; + mtspr(SPRN_HID0, tmp); + isync(); + + /* Enter NAP mode. */ + tmp = mfmsr(); + tmp |= MSR_WE; + mb(); + mtmsr(tmp); + isync(); + + while (1) + ; +} +#endif + +static int __cpuinit smp_85xx_kick_cpu(int nr) { unsigned long flags; const u64 *cpu_rel_addr; __iomem struct epapr_spin_table *spin_table; struct device_node *np; - int n = 0, hw_cpu = get_hard_smp_processor_id(nr); + int hw_cpu = get_hard_smp_processor_id(nr); int ioremappable; + int ret = 0; WARN_ON(nr < 0 || nr >= NR_CPUS); WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS); @@ -139,9 +167,34 @@ 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) { + out_be32(&spin_table->addr_l, 0); + /* + * We don't set the BPTR register here since it already points + * to the boot page properly. + */ + mpic_reset_core(hw_cpu); + + /* wait until core is ready... */ + if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1, + 10000, 100)) { + pr_err("%s: timeout waiting for core %d to reset\n", + __func__, hw_cpu); + ret = -ENOENT; + goto out; + } + + /* clear the acknowledge status */ + __secondary_hold_acknowledge = -1; + } +#endif out_be32(&spin_table->pir, hw_cpu); -#ifdef CONFIG_PPC32 out_be32(&spin_table->addr_l, __pa(__early_start)); if (!ioremappable) @@ -149,11 +202,18 @@ smp_85xx_kick_cpu(int nr) (ulong)spin_table + sizeof(struct epapr_spin_table)); /* Wait a bit for the CPU to ack. */ - while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000)) - mdelay(1); + if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu, + 10000, 100)) { + pr_err("%s: timeout waiting for core %d to ack\n", + __func__, hw_cpu); + ret = -ENOENT; + goto out; + } +out: #else smp_generic_kick_cpu(nr); + out_be32(&spin_table->pir, hw_cpu); out_be64((u64 *)(&spin_table->addr_h), __pa((u64)*((unsigned long long *)generic_secondary_smp_init))); @@ -167,13 +227,15 @@ smp_85xx_kick_cpu(int nr) if (ioremappable) iounmap(spin_table); - pr_debug("waited %d msecs for CPU #%d.\n", n, nr); - - return 0; + return ret; } struct smp_ops_t smp_85xx_ops = { .kick_cpu = smp_85xx_kick_cpu, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = generic_cpu_disable, + .cpu_die = generic_cpu_die, +#endif #ifdef CONFIG_KEXEC .give_timebase = smp_generic_give_timebase, .take_timebase = smp_generic_take_timebase, @@ -277,8 +339,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image) } #endif /* CONFIG_KEXEC */ -static void __init -smp_85xx_setup_cpu(int cpu_nr) +static void __cpuinit smp_85xx_setup_cpu(int cpu_nr) { if (smp_85xx_ops.probe == smp_mpic_probe) mpic_setup_this_cpu(); @@ -329,6 +390,9 @@ void __init mpc85xx_smp_init(void) } 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_ops = &smp_85xx_ops; -- cgit v1.2.3 From 7e0f4872a33c6da38e727cf42c939cc32294fce6 Mon Sep 17 00:00:00 2001 From: Varun Sethi Date: Mon, 9 Jul 2012 18:25:31 +0530 Subject: powepc/booke: Separate out E.HV check and ivor setup code. Move the E.HV check and CPU_FTR_EMB_HV flag manipulation to the cpu setup code. Create a separate routine for E.HV ivors setup. Signed-off-by: Varun Sethi Signed-off-by: Kumar Gala --- arch/powerpc/kernel/cpu_setup_fsl_booke.S | 29 ++++++++++++++++++++++++++--- arch/powerpc/kernel/head_fsl_booke.S | 18 ++++-------------- 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 69fdd2322a66..a55d028aa0da 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -16,6 +16,8 @@ #include #include #include +#include +#include _GLOBAL(__e500_icache_setup) mfspr r0, SPRN_L1CSR1 @@ -73,12 +75,33 @@ _GLOBAL(__setup_cpu_e500v2) mtlr r4 blr _GLOBAL(__setup_cpu_e500mc) - mr r5, r4 - mflr r4 + mflr r5 bl __e500_icache_setup bl __e500_dcache_setup bl __setup_e500mc_ivors - mtlr r4 + /* + * We only want to touch IVOR38-41 if we're running on hardware + * that supports category E.HV. The architectural way to determine + * this is MMUCFG[LPIDSIZE]. + */ + mfspr r3, SPRN_MMUCFG + rlwinm. r3, r3, 0, MMUCFG_LPIDSIZE + beq 1f + bl __setup_ehv_ivors + b 2f +1: + lwz r3, CPU_SPEC_FEATURES(r4) + /* We need this check as cpu_setup is also called for + * the secondary cores. So, if we have already cleared + * the feature on the primary core, avoid doing it on the + * secondary core. + */ + andis. r6, r3, CPU_FTR_EMB_HV@h + beq 2f + rlwinm r3, r3, 0, ~CPU_FTR_EMB_HV + stw r3, CPU_SPEC_FEATURES(r4) +2: + mtlr r5 blr #endif /* Right now, restore and setup are the same thing */ diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index b221541d9861..6f62a737f607 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -895,15 +895,11 @@ _GLOBAL(__setup_e500mc_ivors) mtspr SPRN_IVOR36,r3 li r3,CriticalDoorbell@l mtspr SPRN_IVOR37,r3 + sync + blr - /* - * We only want to touch IVOR38-41 if we're running on hardware - * that supports category E.HV. The architectural way to determine - * this is MMUCFG[LPIDSIZE]. - */ - mfspr r3, SPRN_MMUCFG - andis. r3, r3, MMUCFG_LPIDSIZE@h - beq no_hv +/* setup ehv ivors for */ +_GLOBAL(__setup_ehv_ivors) li r3,GuestDoorbell@l mtspr SPRN_IVOR38,r3 li r3,CriticalGuestDoorbell@l @@ -912,14 +908,8 @@ _GLOBAL(__setup_e500mc_ivors) mtspr SPRN_IVOR40,r3 li r3,Ehvpriv@l mtspr SPRN_IVOR41,r3 -skip_hv_ivors: sync blr -no_hv: - lwz r3, CPU_SPEC_FEATURES(r5) - rlwinm r3, r3, 0, ~CPU_FTR_EMB_HV - stw r3, CPU_SPEC_FEATURES(r5) - b skip_hv_ivors #ifdef CONFIG_SPE /* -- cgit v1.2.3 From 2c71b0cc4a626d8bd02b88b3b92ce18be4d54c6d Mon Sep 17 00:00:00 2001 From: Varun Sethi Date: Mon, 9 Jul 2012 18:28:21 +0530 Subject: powerpc/booke: Merge the 32 bit e5500/e500mc cpu setup code. Merge the 32 bit cpu setup code for e500mc/e5500 and define the "cpu_restore" routine (for e5500/e6500) only for the 64 bit case. The cpu_restore routine is used in the 64 bit case for setting up the secondary cores. Signed-off-by: Varun Sethi Signed-off-by: Kumar Gala --- arch/powerpc/kernel/cpu_setup_fsl_booke.S | 7 +++---- arch/powerpc/kernel/cputable.c | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index a55d028aa0da..021822daa8f6 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -75,6 +75,7 @@ _GLOBAL(__setup_cpu_e500v2) mtlr r4 blr _GLOBAL(__setup_cpu_e500mc) +_GLOBAL(__setup_cpu_e5500) mflr r5 bl __e500_icache_setup bl __e500_dcache_setup @@ -104,19 +105,17 @@ _GLOBAL(__setup_cpu_e500mc) mtlr r5 blr #endif +#ifdef CONFIG_PPC_BOOK3E_64 /* Right now, restore and setup are the same thing */ _GLOBAL(__restore_cpu_e5500) _GLOBAL(__setup_cpu_e5500) mflr r4 bl __e500_icache_setup bl __e500_dcache_setup -#ifdef CONFIG_PPC_BOOK3E_64 bl .__setup_base_ivors bl .setup_perfmon_ivor bl .setup_doorbell_ivors bl .setup_ehv_ivors -#else - bl __setup_e500mc_ivors -#endif mtlr r4 blr +#endif diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 455faa389876..0514c21f138b 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -2016,7 +2016,9 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_cpu_type = "ppc/e500mc", .oprofile_type = PPC_OPROFILE_FSL_EMB, .cpu_setup = __setup_cpu_e5500, +#ifndef CONFIG_PPC32 .cpu_restore = __restore_cpu_e5500, +#endif .machine_check = machine_check_e500mc, .platform = "ppce5500", }, @@ -2034,7 +2036,9 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_cpu_type = "ppc/e6500", .oprofile_type = PPC_OPROFILE_FSL_EMB, .cpu_setup = __setup_cpu_e5500, +#ifndef CONFIG_PPC32 .cpu_restore = __restore_cpu_e5500, +#endif .machine_check = machine_check_e500mc, .platform = "ppce6500", }, -- cgit v1.2.3 From 0778407f836d632cce90e5d9df490a7c5e6e398a Mon Sep 17 00:00:00 2001 From: Varun Sethi Date: Mon, 9 Jul 2012 18:31:51 +0530 Subject: powerpc/booke: Separate out restore_e5500/setup_e5500 routines. For the 64 bit case separate out e5500 cpu_setup and cpu_restore functions. The cpu_setup function (for the primary core) is passed the cpu_spec pointer, which is not there in case of the cpu_restore function. Also, in our case we will have to manipulate the CPU_FTR_EMB_HV flag on the primary core. Signed-off-by: Varun Sethi Signed-off-by: Kumar Gala --- arch/powerpc/kernel/cpu_setup_fsl_booke.S | 32 +++++++++++++++++++++++++++++-- arch/powerpc/kernel/exceptions-64e.S | 18 ++--------------- 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 021822daa8f6..1345e1bc748a 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -105,17 +105,45 @@ _GLOBAL(__setup_cpu_e5500) mtlr r5 blr #endif + #ifdef CONFIG_PPC_BOOK3E_64 -/* Right now, restore and setup are the same thing */ _GLOBAL(__restore_cpu_e5500) -_GLOBAL(__setup_cpu_e5500) mflr r4 bl __e500_icache_setup bl __e500_dcache_setup bl .__setup_base_ivors bl .setup_perfmon_ivor bl .setup_doorbell_ivors + /* + * We only want to touch IVOR38-41 if we're running on hardware + * that supports category E.HV. The architectural way to determine + * this is MMUCFG[LPIDSIZE]. + */ + mfspr r10,SPRN_MMUCFG + rlwinm. r10,r10,0,MMUCFG_LPIDSIZE + beq 1f bl .setup_ehv_ivors +1: mtlr r4 blr + +_GLOBAL(__setup_cpu_e5500) + mflr r5 + bl __e500_icache_setup + bl __e500_dcache_setup + bl .__setup_base_ivors + bl .setup_perfmon_ivor + bl .setup_doorbell_ivors + /* + * We only want to touch IVOR38-41 if we're running on hardware + * that supports category E.HV. The architectural way to determine + * this is MMUCFG[LPIDSIZE]. + */ + mfspr r10,SPRN_MMUCFG + rlwinm. r10,r10,0,MMUCFG_LPIDSIZE + beq 1f + bl .setup_ehv_ivors +1: + mtlr r5 + blr #endif diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 87a82fbdf05a..4684e33a26c3 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -1356,25 +1356,11 @@ _GLOBAL(setup_perfmon_ivor) _GLOBAL(setup_doorbell_ivors) SET_IVOR(36, 0x280) /* Processor Doorbell */ SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */ - - /* Check MMUCFG[LPIDSIZE] to determine if we have category E.HV */ - mfspr r10,SPRN_MMUCFG - rlwinm. r10,r10,0,MMUCFG_LPIDSIZE - beqlr - - SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */ - SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */ blr _GLOBAL(setup_ehv_ivors) - /* - * We may be running as a guest and lack E.HV even on a chip - * that normally has it. - */ - mfspr r10,SPRN_MMUCFG - rlwinm. r10,r10,0,MMUCFG_LPIDSIZE - beqlr - SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */ SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */ + SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */ + SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */ blr -- cgit v1.2.3 From 39be5b4a7f232870aad0b3c130791eacd0d34347 Mon Sep 17 00:00:00 2001 From: Varun Sethi Date: Mon, 9 Jul 2012 18:34:01 +0530 Subject: powerpc/booke: Add CPU_FTR_EMB_HV check for e5500. Added CPU_FTR_EMB_HV feature check for e5500. Signed-off-by: Varun Sethi Signed-off-by: Mihai Caraman Signed-off-by: Kumar Gala --- arch/powerpc/kernel/cpu_setup_fsl_booke.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 1345e1bc748a..dcd881937f7a 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -143,7 +143,13 @@ _GLOBAL(__setup_cpu_e5500) rlwinm. r10,r10,0,MMUCFG_LPIDSIZE beq 1f bl .setup_ehv_ivors + b 2f 1: + ld r10,CPU_SPEC_FEATURES(r4) + LOAD_REG_IMMEDIATE(r9,CPU_FTR_EMB_HV) + andc r10,r10,r9 + std r10,CPU_SPEC_FEATURES(r4) +2: mtlr r5 blr #endif -- cgit v1.2.3 From 688ba1dbee8a49a2efe507cd9ae69634d92bb640 Mon Sep 17 00:00:00 2001 From: Jia Hongtao Date: Fri, 3 Aug 2012 18:14:10 +0800 Subject: powerpc/swiotlb: Enable at early stage and disable if not necessary Remove the dependency on PCI initialization for SWIOTLB initialization. So that PCI can be initialized at proper time. SWIOTLB is partly determined by PCI inbound/outbound map which is assigned in PCI initialization. But swiotlb_init() should be done at the stage of mem_init() which is much earlier than PCI initialization. So we reserve the memory for SWIOTLB first and free it if not necessary. All boards are converted to fit this change. Signed-off-by: Jia Hongtao Signed-off-by: Li Yang Acked-by: Tony Breeds Signed-off-by: Kumar Gala --- arch/powerpc/include/asm/swiotlb.h | 6 ++++++ arch/powerpc/kernel/dma-swiotlb.c | 20 ++++++++++++++++++++ arch/powerpc/mm/mem.c | 3 +-- arch/powerpc/platforms/44x/currituck.c | 10 ++-------- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 1 + arch/powerpc/platforms/85xx/qemu_e500.c | 1 + arch/powerpc/sysdev/fsl_pci.c | 5 +---- 7 files changed, 32 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h index 8979d4cd3d70..de99d6e29430 100644 --- a/arch/powerpc/include/asm/swiotlb.h +++ b/arch/powerpc/include/asm/swiotlb.h @@ -22,4 +22,10 @@ int __init swiotlb_setup_bus_notifier(void); extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev); +#ifdef CONFIG_SWIOTLB +void swiotlb_detect_4g(void); +#else +static inline void swiotlb_detect_4g(void) {} +#endif + #endif /* __ASM_SWIOTLB_H */ diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index a720b54b971c..bd1a2aba599f 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -105,3 +105,23 @@ int __init swiotlb_setup_bus_notifier(void) &ppc_swiotlb_plat_bus_notifier); return 0; } + +void swiotlb_detect_4g(void) +{ + if ((memblock_end_of_DRAM() - 1) > 0xffffffff) + ppc_swiotlb_enable = 1; +} + +static int __init swiotlb_late_init(void) +{ + if (ppc_swiotlb_enable) { + swiotlb_print_info(); + set_pci_dma_ops(&swiotlb_dma_ops); + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; + } else { + swiotlb_free(); + } + + return 0; +} +subsys_initcall(swiotlb_late_init); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 44cf2b20503d..0dba5066c22a 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -300,8 +300,7 @@ void __init mem_init(void) unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; #ifdef CONFIG_SWIOTLB - if (ppc_swiotlb_enable) - swiotlb_init(1); + swiotlb_init(0); #endif num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT; diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c index 9f6c33d63a42..6bd89a0e0dea 100644 --- a/arch/powerpc/platforms/44x/currituck.c +++ b/arch/powerpc/platforms/44x/currituck.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include @@ -159,13 +158,8 @@ static void __init ppc47x_setup_arch(void) /* No need to check the DMA config as we /know/ our windows are all of * RAM. Lets hope that doesn't change */ -#ifdef CONFIG_SWIOTLB - if ((memblock_end_of_DRAM() - 1) > 0xffffffff) { - ppc_swiotlb_enable = 1; - set_pci_dma_ops(&swiotlb_dma_ops); - ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; - } -#endif + swiotlb_detect_4g(); + ppc47x_smp_init(); } diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 6d3265fe7718..56f8c8f674df 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -159,6 +159,7 @@ static void __init mpc85xx_ds_setup_arch(void) if (ppc_md.progress) ppc_md.progress("mpc85xx_ds_setup_arch()", 0); + swiotlb_detect_4g(); mpc85xx_ds_pci_init(); mpc85xx_smp_init(); diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c index 95a2e53af71b..3c5490c8423f 100644 --- a/arch/powerpc/platforms/85xx/qemu_e500.c +++ b/arch/powerpc/platforms/85xx/qemu_e500.c @@ -42,6 +42,7 @@ static void __init qemu_e500_setup_arch(void) ppc_md.progress("qemu_e500_setup_arch()", 0); fsl_pci_init(); + swiotlb_detect_4g(); mpc85xx_smp_init(); } diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 6938792ccfd9..da7a3d7f54cc 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -872,11 +872,8 @@ void __devinit fsl_pci_init(void) * we need SWIOTLB to handle buffers located outside of * dma capable memory region */ - if (memblock_end_of_DRAM() - 1 > max) { + if (memblock_end_of_DRAM() - 1 > max) ppc_swiotlb_enable = 1; - set_pci_dma_ops(&swiotlb_dma_ops); - ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; - } #endif } #endif -- cgit v1.2.3