diff options
Diffstat (limited to 'kernel/panic.c')
| -rw-r--r-- | kernel/panic.c | 60 |
1 files changed, 27 insertions, 33 deletions
diff --git a/kernel/panic.c b/kernel/panic.c index 3b16cd93fa7d..4c13b1a88ebb 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -24,6 +24,9 @@ | |||
| 24 | #include <linux/nmi.h> | 24 | #include <linux/nmi.h> |
| 25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
| 26 | 26 | ||
| 27 | #define PANIC_TIMER_STEP 100 | ||
| 28 | #define PANIC_BLINK_SPD 18 | ||
| 29 | |||
| 27 | int panic_on_oops; | 30 | int panic_on_oops; |
| 28 | static unsigned long tainted_mask; | 31 | static unsigned long tainted_mask; |
| 29 | static int pause_on_oops; | 32 | static int pause_on_oops; |
| @@ -36,36 +39,15 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list); | |||
| 36 | 39 | ||
| 37 | EXPORT_SYMBOL(panic_notifier_list); | 40 | EXPORT_SYMBOL(panic_notifier_list); |
| 38 | 41 | ||
| 39 | /* Returns how long it waited in ms */ | 42 | static long no_blink(int state) |
| 40 | long (*panic_blink)(long time); | ||
| 41 | EXPORT_SYMBOL(panic_blink); | ||
| 42 | |||
| 43 | static void panic_blink_one_second(void) | ||
| 44 | { | 43 | { |
| 45 | static long i = 0, end; | 44 | return 0; |
| 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 | } | 45 | } |
| 68 | 46 | ||
| 47 | /* Returns how long it waited in ms */ | ||
| 48 | long (*panic_blink)(int state); | ||
| 49 | EXPORT_SYMBOL(panic_blink); | ||
| 50 | |||
| 69 | /** | 51 | /** |
| 70 | * panic - halt the system | 52 | * panic - halt the system |
| 71 | * @fmt: The text string to print | 53 | * @fmt: The text string to print |
| @@ -78,7 +60,8 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 78 | { | 60 | { |
| 79 | static char buf[1024]; | 61 | static char buf[1024]; |
| 80 | va_list args; | 62 | va_list args; |
| 81 | long i; | 63 | long i, i_next = 0; |
| 64 | int state = 0; | ||
| 82 | 65 | ||
| 83 | /* | 66 | /* |
| 84 | * It's possible to come here directly from a panic-assertion and | 67 | * It's possible to come here directly from a panic-assertion and |
| @@ -117,6 +100,9 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 117 | 100 | ||
| 118 | bust_spinlocks(0); | 101 | bust_spinlocks(0); |
| 119 | 102 | ||
| 103 | if (!panic_blink) | ||
| 104 | panic_blink = no_blink; | ||
| 105 | |||
| 120 | if (panic_timeout > 0) { | 106 | if (panic_timeout > 0) { |
| 121 | /* | 107 | /* |
| 122 | * Delay timeout seconds before rebooting the machine. | 108 | * Delay timeout seconds before rebooting the machine. |
| @@ -124,9 +110,13 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 124 | */ | 110 | */ |
| 125 | printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); | 111 | printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout); |
| 126 | 112 | ||
| 127 | for (i = 0; i < panic_timeout; i++) { | 113 | for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) { |
| 128 | touch_nmi_watchdog(); | 114 | touch_nmi_watchdog(); |
| 129 | panic_blink_one_second(); | 115 | if (i >= i_next) { |
| 116 | i += panic_blink(state ^= 1); | ||
| 117 | i_next = i + 3600 / PANIC_BLINK_SPD; | ||
| 118 | } | ||
| 119 | mdelay(PANIC_TIMER_STEP); | ||
| 130 | } | 120 | } |
| 131 | /* | 121 | /* |
| 132 | * This will not be a clean reboot, with everything | 122 | * This will not be a clean reboot, with everything |
| @@ -152,9 +142,13 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 152 | } | 142 | } |
| 153 | #endif | 143 | #endif |
| 154 | local_irq_enable(); | 144 | local_irq_enable(); |
| 155 | while (1) { | 145 | for (i = 0; ; i += PANIC_TIMER_STEP) { |
| 156 | touch_softlockup_watchdog(); | 146 | touch_softlockup_watchdog(); |
| 157 | panic_blink_one_second(); | 147 | if (i >= i_next) { |
| 148 | i += panic_blink(state ^= 1); | ||
| 149 | i_next = i + 3600 / PANIC_BLINK_SPD; | ||
| 150 | } | ||
| 151 | mdelay(PANIC_TIMER_STEP); | ||
| 158 | } | 152 | } |
| 159 | } | 153 | } |
| 160 | 154 | ||
| @@ -344,7 +338,7 @@ static int init_oops_id(void) | |||
| 344 | } | 338 | } |
| 345 | late_initcall(init_oops_id); | 339 | late_initcall(init_oops_id); |
| 346 | 340 | ||
| 347 | static void print_oops_end_marker(void) | 341 | void print_oops_end_marker(void) |
| 348 | { | 342 | { |
| 349 | init_oops_id(); | 343 | init_oops_id(); |
| 350 | printk(KERN_WARNING "---[ end trace %016llx ]---\n", | 344 | printk(KERN_WARNING "---[ end trace %016llx ]---\n", |
