aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2010-07-09 01:34:00 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-09 02:11:19 -0400
commit850f22d5688941ea51628f3f8f8dcf3baff409ff (patch)
tree99e3ea43035a7d96b7f7bea81428186dea6ad000
parent0e37d25950f4fd5a7d74723e6ce608aaa972d24c (diff)
powerpc/book3e: Resend doorbell exceptions to ourself
If we are soft disabled and receive a doorbell exception we don't process it immediately. This means we need to check on the way out of irq restore if there are any doorbell exceptions to process. The problem is at that point we don't know what our regs are, and that in turn makes xmon unhappy. To workaround the problem, instead of checking for and processing doorbells, we check for any doorbells and if there were any we send ourselves another. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/dbell.h1
-rw-r--r--arch/powerpc/kernel/dbell.c10
-rw-r--r--arch/powerpc/kernel/irq.c4
3 files changed, 13 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index ced7e487ca27..0893ab9343a6 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -29,6 +29,7 @@ enum ppc_dbell {
29 29
30extern void doorbell_message_pass(int target, int msg); 30extern void doorbell_message_pass(int target, int msg);
31extern void doorbell_exception(struct pt_regs *regs); 31extern void doorbell_exception(struct pt_regs *regs);
32extern void doorbell_check_self(void);
32extern void doorbell_setup_this_cpu(void); 33extern void doorbell_setup_this_cpu(void);
33 34
34static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag) 35static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index f7b518894c80..3307a52d797f 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -81,6 +81,16 @@ out:
81 set_irq_regs(old_regs); 81 set_irq_regs(old_regs);
82} 82}
83 83
84void doorbell_check_self(void)
85{
86 struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info);
87
88 if (!info->messages)
89 return;
90
91 ppc_msgsnd(PPC_DBELL, 0, info->tag);
92}
93
84#else /* CONFIG_SMP */ 94#else /* CONFIG_SMP */
85void doorbell_exception(struct pt_regs *regs) 95void doorbell_exception(struct pt_regs *regs)
86{ 96{
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 2f6dc7faf6de..8f96d3198905 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -156,8 +156,8 @@ notrace void raw_local_irq_restore(unsigned long en)
156 return; 156 return;
157 157
158#if defined(CONFIG_BOOKE) && defined(CONFIG_SMP) 158#if defined(CONFIG_BOOKE) && defined(CONFIG_SMP)
159 /* Check for pending doorbell interrupts on SMP */ 159 /* Check for pending doorbell interrupts and resend to ourself */
160 doorbell_exception(NULL); 160 doorbell_check_self();
161#endif 161#endif
162 162
163 /* 163 /*