aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/dbell.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/dbell.c')
-rw-r--r--arch/powerpc/kernel/dbell.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index 1493734cd87..d55c76c571f 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -13,32 +13,45 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/threads.h>
+#include <linux/hardirq.h>
#include <asm/dbell.h>
+#include <asm/irq_regs.h>
#ifdef CONFIG_SMP
-unsigned long dbell_smp_message[NR_CPUS];
+void doorbell_setup_this_cpu(void)
+{
+ unsigned long tag = mfspr(SPRN_DOORBELL_CPUTAG) & PPC_DBELL_TAG_MASK;
+
+ smp_muxed_ipi_set_data(smp_processor_id(), tag);
+}
+
+void doorbell_cause_ipi(int cpu, unsigned long data)
+{
+ /* Order previous accesses vs. msgsnd, which is treated as a store */
+ mb();
+ ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, data);
+}
+
+void doorbell_exception(struct pt_regs *regs)
+{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+
+ may_hard_irq_enable();
+
+ __get_cpu_var(irq_stat).doorbell_irqs++;
-void smp_dbell_message_pass(int target, int msg)
+ smp_ipi_demux();
+
+ irq_exit();
+ set_irq_regs(old_regs);
+}
+#else /* CONFIG_SMP */
+void doorbell_exception(struct pt_regs *regs)
{
- 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);
- }
+ printk(KERN_WARNING "Received doorbell on non-smp system\n");
}
-#endif
+#endif /* CONFIG_SMP */
+