aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/dbell.h3
-rw-r--r--arch/powerpc/include/asm/smp.h16
-rw-r--r--arch/powerpc/include/asm/xics.h2
-rw-r--r--arch/powerpc/kernel/dbell.c46
-rw-r--r--arch/powerpc/kernel/irq.c4
-rw-r--r--arch/powerpc/kernel/smp.c94
-rw-r--r--arch/powerpc/platforms/85xx/smp.c6
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c16
-rw-r--r--arch/powerpc/platforms/iseries/irq.c3
-rw-r--r--arch/powerpc/platforms/iseries/smp.c23
-rw-r--r--arch/powerpc/platforms/iseries/smp.h6
-rw-r--r--arch/powerpc/platforms/powermac/smp.c27
-rw-r--r--arch/powerpc/platforms/pseries/smp.c3
-rw-r--r--arch/powerpc/platforms/wsp/smp.c3
-rw-r--r--arch/powerpc/sysdev/xics/icp-hv.c10
-rw-r--r--arch/powerpc/sysdev/xics/icp-native.c10
-rw-r--r--arch/powerpc/sysdev/xics/xics-common.c30
17 files changed, 126 insertions, 176 deletions
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index 3269eb49640a..9c70d0ca96d4 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -27,9 +27,8 @@ enum ppc_dbell {
27 PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */ 27 PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */
28}; 28};
29 29
30extern void doorbell_message_pass(int cpu, int msg); 30extern void doorbell_cause_ipi(int cpu, unsigned long data);
31extern void doorbell_exception(struct pt_regs *regs); 31extern void doorbell_exception(struct pt_regs *regs);
32extern void doorbell_check_self(void);
33extern void doorbell_setup_this_cpu(void); 32extern void doorbell_setup_this_cpu(void);
34 33
35static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag) 34static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 6f7c95c0027a..26f861560c51 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -20,6 +20,7 @@
20#include <linux/threads.h> 20#include <linux/threads.h>
21#include <linux/cpumask.h> 21#include <linux/cpumask.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/irqreturn.h>
23 24
24#ifndef __ASSEMBLY__ 25#ifndef __ASSEMBLY__
25 26
@@ -37,6 +38,7 @@ extern void cpu_die(void);
37 38
38struct smp_ops_t { 39struct smp_ops_t {
39 void (*message_pass)(int cpu, int msg); 40 void (*message_pass)(int cpu, int msg);
41 void (*cause_ipi)(int cpu, unsigned long data);
40 int (*probe)(void); 42 int (*probe)(void);
41 int (*kick_cpu)(int nr); 43 int (*kick_cpu)(int nr);
42 void (*setup_cpu)(int nr); 44 void (*setup_cpu)(int nr);
@@ -49,7 +51,6 @@ struct smp_ops_t {
49}; 51};
50 52
51extern void smp_send_debugger_break(void); 53extern void smp_send_debugger_break(void);
52extern void smp_message_recv(int);
53extern void start_secondary_resume(void); 54extern void start_secondary_resume(void);
54extern void __devinit smp_generic_give_timebase(void); 55extern void __devinit smp_generic_give_timebase(void);
55extern void __devinit smp_generic_take_timebase(void); 56extern void __devinit smp_generic_take_timebase(void);
@@ -109,13 +110,16 @@ extern int cpu_to_core_id(int cpu);
109#define PPC_MSG_CALL_FUNC_SINGLE 2 110#define PPC_MSG_CALL_FUNC_SINGLE 2
110#define PPC_MSG_DEBUGGER_BREAK 3 111#define PPC_MSG_DEBUGGER_BREAK 3
111 112
112/* 113/* for irq controllers that have dedicated ipis per message (4) */
113 * irq controllers that have dedicated ipis per message and don't
114 * need additional code in the action handler may use this
115 */
116extern int smp_request_message_ipi(int virq, int message); 114extern int smp_request_message_ipi(int virq, int message);
117extern const char *smp_ipi_name[]; 115extern const char *smp_ipi_name[];
118 116
117/* for irq controllers with only a single ipi */
118extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
119extern void smp_muxed_ipi_message_pass(int cpu, int msg);
120extern void smp_muxed_ipi_resend(void);
121extern irqreturn_t smp_ipi_demux(void);
122
119void smp_init_iSeries(void); 123void smp_init_iSeries(void);
120void smp_init_pSeries(void); 124void smp_init_pSeries(void);
121void smp_init_cell(void); 125void smp_init_cell(void);
@@ -185,6 +189,8 @@ extern unsigned long __secondary_hold_spinloop;
185extern unsigned long __secondary_hold_acknowledge; 189extern unsigned long __secondary_hold_acknowledge;
186extern char __secondary_hold; 190extern char __secondary_hold;
187 191
192extern irqreturn_t debug_ipi_action(int irq, void *data);
193
188#endif /* __ASSEMBLY__ */ 194#endif /* __ASSEMBLY__ */
189 195
190#endif /* __KERNEL__ */ 196#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
index 1750c8dae1fa..b183a4062011 100644
--- a/arch/powerpc/include/asm/xics.h
+++ b/arch/powerpc/include/asm/xics.h
@@ -40,7 +40,7 @@ struct icp_ops {
40 void (*teardown_cpu)(void); 40 void (*teardown_cpu)(void);
41 void (*flush_ipi)(void); 41 void (*flush_ipi)(void);
42#ifdef CONFIG_SMP 42#ifdef CONFIG_SMP
43 void (*message_pass)(int cpu, int msg); 43 void (*cause_ipi)(int cpu, unsigned long data);
44 irq_handler_t ipi_action; 44 irq_handler_t ipi_action;
45#endif 45#endif
46}; 46};
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index e49b24c84133..2cc451aaaca7 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -13,65 +13,35 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/smp.h> 14#include <linux/smp.h>
15#include <linux/threads.h> 15#include <linux/threads.h>
16#include <linux/percpu.h> 16#include <linux/hardirq.h>
17 17
18#include <asm/dbell.h> 18#include <asm/dbell.h>
19#include <asm/irq_regs.h> 19#include <asm/irq_regs.h>
20 20
21#ifdef CONFIG_SMP 21#ifdef CONFIG_SMP
22struct doorbell_cpu_info {
23 unsigned long messages; /* current messages bits */
24 unsigned int tag; /* tag value */
25};
26
27static DEFINE_PER_CPU(struct doorbell_cpu_info, doorbell_cpu_info);
28
29void doorbell_setup_this_cpu(void) 22void doorbell_setup_this_cpu(void)
30{ 23{
31 struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); 24 unsigned long tag = mfspr(SPRN_PIR) & 0x3fff;
32 25
33 info->messages = 0; 26 smp_muxed_ipi_set_data(smp_processor_id(), tag);
34 info->tag = mfspr(SPRN_PIR) & 0x3fff;
35} 27}
36 28
37void doorbell_message_pass(int cpu, int msg) 29void doorbell_cause_ipi(int cpu, unsigned long data)
38{ 30{
39 struct doorbell_cpu_info *info; 31 ppc_msgsnd(PPC_DBELL, 0, data);
40
41 info = &per_cpu(doorbell_cpu_info, cpu);
42 set_bit(msg, &info->messages);
43 ppc_msgsnd(PPC_DBELL, 0, info->tag);
44} 32}
45 33
46void doorbell_exception(struct pt_regs *regs) 34void doorbell_exception(struct pt_regs *regs)
47{ 35{
48 struct pt_regs *old_regs = set_irq_regs(regs); 36 struct pt_regs *old_regs = set_irq_regs(regs);
49 struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info);
50 int msg;
51 37
52 /* Warning: regs can be NULL when called from irq enable */ 38 irq_enter();
53 39
54 if (!info->messages || (num_online_cpus() < 2)) 40 smp_ipi_demux();
55 goto out;
56 41
57 for (msg = 0; msg < 4; msg++) 42 irq_exit();
58 if (test_and_clear_bit(msg, &info->messages))
59 smp_message_recv(msg);
60
61out:
62 set_irq_regs(old_regs); 43 set_irq_regs(old_regs);
63} 44}
64