aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index c787333282b8..3b16cd93fa7d 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -36,15 +36,36 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
36 36
37EXPORT_SYMBOL(panic_notifier_list); 37EXPORT_SYMBOL(panic_notifier_list);
38 38
39static long no_blink(long time)
40{
41 return 0;
42}
43
44/* Returns how long it waited in ms */ 39/* Returns how long it waited in ms */
45long (*panic_blink)(long time); 40long (*panic_blink)(long time);
46EXPORT_SYMBOL(panic_blink); 41EXPORT_SYMBOL(panic_blink);
47 42
43static void panic_blink_one_second(void)
44{
45 static long i = 0, end;
46
47 if (panic_blink) {
48 end = i + MSEC_PER_SEC;
49
50 while (i < end) {
51 i += panic_blink(i);
52 mdelay(1);
53 i++;
54 }
55 } else {
56 /*
57 * When running under a hypervisor a small mdelay may get
58 * rounded up to the hypervisor timeslice. For example, with
59 * a 1ms in 10ms hypervisor timeslice we might inflate a
60 * mdelay(1) loop by 10x.
61 *
62 * If we have nothing to blink, spin on 1 second calls to
63 * mdelay to avoid this.
64 */
65 mdelay(MSEC_PER_SEC);
66 }
67}
68
48/** 69/**
49 * panic - halt the system 70 * panic - halt the system
50 * @fmt: The text string to print 71 * @fmt: The text string to print
@@ -66,6 +87,7 @@ NORET_TYPE void panic(const char * fmt, ...)
66 */ 87 */
67 preempt_disable(); 88 preempt_disable();
68 89
90 console_verbose();
69 bust_spinlocks(1); 91 bust_spinlocks(1);
70 va_start(args, fmt); 92 va_start(args, fmt);
71 vsnprintf(buf, sizeof(buf), fmt, args); 93 vsnprintf(buf, sizeof(buf), fmt, args);
@@ -95,9 +117,6 @@ NORET_TYPE void panic(const char * fmt, ...)
95 117
96 bust_spinlocks(0); 118 bust_spinlocks(0);
97 119
98 if (!panic_blink)
99 panic_blink = no_blink;
100
101 if (panic_timeout > 0) { 120 if (panic_timeout > 0) {
102 /* 121 /*
103 * Delay timeout seconds before rebooting the machine. 122 * Delay timeout seconds before rebooting the machine.
@@ -105,11 +124,9 @@ NORET_TYPE void panic(const char * fmt, ...)
105 */ 124 */
106 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); 125 printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
107 126
108 for (i = 0; i < panic_timeout*1000; ) { 127 for (i = 0; i < panic_timeout; i++) {
109 touch_nmi_watchdog(); 128 touch_nmi_watchdog();
110 i += panic_blink(i); 129 panic_blink_one_second();
111 mdelay(1);
112 i++;
113 } 130 }
114 /* 131 /*
115 * This will not be a clean reboot, with everything 132 * This will not be a clean reboot, with everything
@@ -135,11 +152,9 @@ NORET_TYPE void panic(const char * fmt, ...)
135 } 152 }
136#endif 153#endif
137 local_irq_enable(); 154 local_irq_enable();
138 for (i = 0; ; ) { 155 while (1) {
139 touch_softlockup_watchdog(); 156 touch_softlockup_watchdog();
140 i += panic_blink(i); 157 panic_blink_one_second();
141 mdelay(1);
142 i++;
143 } 158 }
144} 159}
145 160
@@ -164,6 +179,7 @@ static const struct tnt tnts[] = {
164 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' }, 179 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
165 { TAINT_WARN, 'W', ' ' }, 180 { TAINT_WARN, 'W', ' ' },
166 { TAINT_CRAP, 'C', ' ' }, 181 { TAINT_CRAP, 'C', ' ' },
182 { TAINT_FIRMWARE_WORKAROUND, 'I', ' ' },
167}; 183};
168 184
169/** 185/**
@@ -180,6 +196,7 @@ static const struct tnt tnts[] = {
180 * 'A' - ACPI table overridden. 196 * 'A' - ACPI table overridden.
181 * 'W' - Taint on warning. 197 * 'W' - Taint on warning.
182 * 'C' - modules from drivers/staging are loaded. 198 * 'C' - modules from drivers/staging are loaded.
199 * 'I' - Working around severe firmware bug.
183 * 200 *
184 * The string is overwritten by the next call to print_tainted(). 201 * The string is overwritten by the next call to print_tainted().
185 */ 202 */
@@ -351,7 +368,8 @@ struct slowpath_args {
351 va_list args; 368 va_list args;
352}; 369};
353 370
354static void warn_slowpath_common(const char *file, int line, void *caller, struct slowpath_args *args) 371static void warn_slowpath_common(const char *file, int line, void *caller,
372 unsigned taint, struct slowpath_args *args)
355{ 373{
356 const char *board; 374 const char *board;
357 375
@@ -367,7 +385,7 @@ static void warn_slowpath_common(const char *file, int line, void *caller, struc
367 print_modules(); 385 print_modules();
368 dump_stack(); 386 dump_stack();
369 print_oops_end_marker(); 387 print_oops_end_marker();
370 add_taint(TAINT_WARN); 388 add_taint(taint);
371} 389}
372 390
373void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) 391void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
@@ -376,14 +394,29 @@ void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
376 394
377 args.fmt = fmt; 395 args.fmt = fmt;
378 va_start(args.args, fmt); 396 va_start(args.args, fmt);
379 warn_slowpath_common(file, line, __builtin_return_address(0), &args); 397 warn_slowpath_common(file, line, __builtin_return_address(0),
398 TAINT_WARN, &args);
380 va_end(args.args); 399 va_end(args.args);
381} 400}
382EXPORT_SYMBOL(warn_slowpath_fmt); 401EXPORT_SYMBOL(warn_slowpath_fmt);
383 402
403void warn_slowpath_fmt_taint(const char *file, int line,
404 unsigned taint, const char *fmt, ...)
405{
406 struct slowpath_args args;
407
408 args.fmt = fmt;
409 va_start(args.args, fmt);
410 warn_slowpath_common(file, line, __builtin_return_address(0),
411 taint, &args);
412 va_end(args.args);
413}
414EXPORT_SYMBOL(warn_slowpath_fmt_taint);
415
384void warn_slowpath_null(const char *file, int line) 416void warn_slowpath_null(const char *file, int line)
385{ 417{
386 warn_slowpath_common(file, line, __builtin_return_address(0), NULL); 418 warn_slowpath_common(file, line, __builtin_return_address(0),
419 TAINT_WARN, NULL);
387} 420}
388EXPORT_SYMBOL(warn_slowpath_null); 421EXPORT_SYMBOL(warn_slowpath_null);
389#endif 422#endif