aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-08-03 03:31:54 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-03 03:56:52 -0400
commit47cab6a722d44c71c4f8224017ef548522243cf4 (patch)
tree477bbe67a203d9704792d6ce46a9f1199587ddfe
parentc1dc0b9c0c8979ce4d411caadff5c0d79dee58bc (diff)
debug lockups: Improve lockup detection, fix generic arch fallback
As Andrew noted, my previous patch ("debug lockups: Improve lockup detection") broke/removed SysRq-L support from architecture that do not provide a __trigger_all_cpu_backtrace implementation. Restore a fallback path and clean up the SysRq-L machinery a bit: - Rename the arch method to arch_trigger_all_cpu_backtrace() - Simplify the define - Document the method a bit - in the hope of more architectures adding support for it. [ The patch touches Sparc code for the rename. ] Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: "David S. Miller" <davem@davemloft.net> LKML-Reference: <20090802140809.7ec4bb6b.akpm@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/sparc/include/asm/irq_64.h4
-rw-r--r--arch/sparc/kernel/process_64.c4
-rw-r--r--arch/x86/include/asm/nmi.h4
-rw-r--r--arch/x86/kernel/apic/nmi.c2
-rw-r--r--drivers/char/sysrq.c15
-rw-r--r--include/linux/nmi.h19
6 files changed, 38 insertions, 10 deletions
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h
index 1934f2cbf513..a0b443cb3c1f 100644
--- a/arch/sparc/include/asm/irq_64.h
+++ b/arch/sparc/include/asm/irq_64.h
@@ -89,8 +89,8 @@ static inline unsigned long get_softint(void)
89 return retval; 89 return retval;
90} 90}
91 91
92void __trigger_all_cpu_backtrace(void); 92void arch_trigger_all_cpu_backtrace(void);
93#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() 93#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
94 94
95extern void *hardirq_stack[NR_CPUS]; 95extern void *hardirq_stack[NR_CPUS];
96extern void *softirq_stack[NR_CPUS]; 96extern void *softirq_stack[NR_CPUS];
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index 4041f94e7724..18d67854a1b8 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -251,7 +251,7 @@ static void __global_reg_poll(struct global_reg_snapshot *gp)
251 } 251 }
252} 252}
253 253
254void __trigger_all_cpu_backtrace(void) 254void arch_trigger_all_cpu_backtrace(void)
255{ 255{
256 struct thread_info *tp = current_thread_info(); 256 struct thread_info *tp = current_thread_info();
257 struct pt_regs *regs = get_irq_regs(); 257 struct pt_regs *regs = get_irq_regs();
@@ -304,7 +304,7 @@ void __trigger_all_cpu_backtrace(void)
304 304
305static void sysrq_handle_globreg(int key, struct tty_struct *tty) 305static void sysrq_handle_globreg(int key, struct tty_struct *tty)
306{ 306{
307 __trigger_all_cpu_backtrace(); 307 arch_trigger_all_cpu_backtrace();
308} 308}
309 309
310static struct sysrq_key_op sparc_globalreg_op = { 310static struct sysrq_key_op sparc_globalreg_op = {
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index c86e5ed4af51..e63cf7d441e1 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -45,8 +45,8 @@ extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
45 void __user *, size_t *, loff_t *); 45 void __user *, size_t *, loff_t *);
46extern int unknown_nmi_panic; 46extern int unknown_nmi_panic;
47 47
48void __trigger_all_cpu_backtrace(void); 48void arch_trigger_all_cpu_backtrace(void);
49#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() 49#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
50 50
51static inline void localise_nmi_watchdog(void) 51static inline void localise_nmi_watchdog(void)
52{ 52{
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index 1bb1ac20e9ec..db7220220d09 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -554,7 +554,7 @@ int do_nmi_callback(struct pt_regs *regs, int cpu)
554 return 0; 554 return 0;
555} 555}
556 556
557void __trigger_all_cpu_backtrace(void) 557void arch_trigger_all_cpu_backtrace(void)
558{ 558{
559 int i; 559 int i;
560 560
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 165f307f30e8..50eecfe1d724 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -223,7 +223,20 @@ static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
223 223
224static void sysrq_handle_showallcpus(int key, struct tty_struct *tty) 224static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
225{ 225{
226 trigger_all_cpu_backtrace(); 226 /*
227 * Fall back to the workqueue based printing if the
228 * backtrace printing did not succeed or the
229 * architecture has no support for it:
230 */
231 if (!trigger_all_cpu_backtrace()) {
232 struct pt_regs *regs = get_irq_regs();
233
234 if (regs) {
235 printk(KERN_INFO "CPU%d:\n", smp_processor_id());
236 show_regs(regs);
237 }
238 schedule_work(&sysrq_showallcpus);
239 }
227} 240}
228 241
229static struct sysrq_key_op sysrq_showallcpus_op = { 242static struct sysrq_key_op sysrq_showallcpus_op = {
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index 29af2d5df097..b752e807adde 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -28,8 +28,23 @@ static inline void acpi_nmi_disable(void) { }
28static inline void acpi_nmi_enable(void) { } 28static inline void acpi_nmi_enable(void) { }
29#endif 29#endif
30 30
31#ifndef trigger_all_cpu_backtrace 31/*
32#define trigger_all_cpu_backtrace() do { } while (0) 32 * Create trigger_all_cpu_backtrace() out of the arch-provided
33 * base function. Return whether such support was available,
34 * to allow calling code to fall back to some other mechanism:
35 */
36#ifdef arch_trigger_all_cpu_backtrace
37static inline bool trigger_all_cpu_backtrace(void)
38{
39 arch_trigger_all_cpu_backtrace();
40
41 return true;
42}
43#else
44static inline bool trigger_all_cpu_backtrace(void)
45{
46 return false;
47}
33#endif 48#endif
34 49
35#endif 50#endif