diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2009-02-12 13:54:53 +0000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-02-23 15:53:03 +1100 |
commit | 620165f971753c2c451c880796bac7cd66f3534a (patch) | |
tree | 1ec36dc067ff0af865f4f6954dbea84ef4205294 /arch/powerpc/kernel | |
parent | 6ed8d12849d651c646c108807754a544d2e506f1 (diff) |
powerpc: Add support for using doorbells for SMP IPI
The e500mc supports the new msgsnd/doorbell mechanisms that were added in
the Power ISA 2.05 architecture. We use the normal level doorbell for
doing SMP IPIs at this point.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/dbell.c | 44 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 21 |
4 files changed, 71 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 583ba6493a6..dfec3d2790b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -59,7 +59,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o obj-$(CONFIG_44x) += cpu_setup_44x.o -obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o +obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o extra-$(CONFIG_PPC_STD_MMU) := head_32.o extra-$(CONFIG_PPC64) := head_64.o diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c new file mode 100644 index 00000000000..1493734cd87 --- /dev/null +++ b/arch/powerpc/kernel/dbell.c @@ -0,0 +1,44 @@ +/* + * Author: Kumar Gala <galak@kernel.crashing.org> + * + * Copyright 2009 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/smp.h> +#include <linux/threads.h> + +#include <asm/dbell.h> + +#ifdef CONFIG_SMP +unsigned long dbell_smp_message[NR_CPUS]; + +void smp_dbell_message_pass(int target, int msg) +{ + int i; + + if(target < NR_CPUS) { + set_bit(msg, &dbell_smp_message[target]); + ppc_msgsnd(PPC_DBELL, 0, target); + } + else if(target == MSG_ALL_BUT_SELF) { + for_each_online_cpu(i) { + if (i == smp_processor_id()) + continue; + set_bit(msg, &dbell_smp_message[i]); + ppc_msgsnd(PPC_DBELL, 0, i); + } + } + else { /* target == MSG_ALL */ + for_each_online_cpu(i) + set_bit(msg, &dbell_smp_message[i]); + ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); + } +} +#endif diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 4ea6e1a7e4b..4c22620d009 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -698,7 +698,9 @@ interrupt_base: /* Performance Monitor */ EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) - EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD) + EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD) + + CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception) /* Debug Interrupt */ DEBUG_DEBUG_EXCEPTION @@ -921,6 +923,8 @@ _GLOBAL(__setup_e500mc_ivors) mtspr SPRN_IVOR35,r3 li r3,Doorbell@l mtspr SPRN_IVOR36,r3 + li r3,CriticalDoorbell@l + mtspr SPRN_IVOR37,r3 sync blr diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 970d66ec465..678fbff0d20 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -53,6 +53,9 @@ #endif #include <asm/kexec.h> #include <asm/ppc-opcode.h> +#ifdef CONFIG_FSL_BOOKE +#include <asm/dbell.h> +#endif #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) int (*__debugger)(struct pt_regs *regs); @@ -1122,6 +1125,24 @@ void vsx_assist_exception(struct pt_regs *regs) #endif /* CONFIG_VSX */ #ifdef CONFIG_FSL_BOOKE + +void doorbell_exception(struct pt_regs *regs) +{ +#ifdef CONFIG_SMP + int cpu = smp_processor_id(); + int msg; + + if (num_online_cpus() < 2) + return; + + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &dbell_smp_message[cpu])) + smp_message_recv(msg); +#else + printk(KERN_WARNING "Received doorbell on non-smp system\n"); +#endif +} + void CacheLockingException(struct pt_regs *regs, unsigned long address, unsigned long error_code) { |