diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/power/main.c | 7 | ||||
-rw-r--r-- | kernel/printk.c | 41 |
2 files changed, 48 insertions, 0 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c index 19122cf6d82..3fdc1f42376 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -132,6 +132,9 @@ static inline int suspend_test(int level) { return 0; } #endif /* CONFIG_PM_SLEEP */ +int global_inside_suspend; +EXPORT_SYMBOL(global_inside_suspend); + #ifdef CONFIG_SUSPEND #ifdef CONFIG_PM_TEST_SUSPEND @@ -322,6 +325,8 @@ int suspend_devices_and_enter(suspend_state_t state) if (!suspend_ops) return -ENOSYS; + global_inside_suspend = 1; + if (suspend_ops->begin) { error = suspend_ops->begin(state); if (error) @@ -365,6 +370,8 @@ int suspend_devices_and_enter(suspend_state_t state) Close: if (suspend_ops->end) suspend_ops->end(); + global_inside_suspend = 0; + return error; Recover_platform: diff --git a/kernel/printk.c b/kernel/printk.c index f492f1583d7..c81ad8638aa 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,8 +32,12 @@ #include <linux/security.h> #include <linux/bootmem.h> #include <linux/syscalls.h> +#include <linux/jiffies.h> +#include <linux/suspend.h> #include <asm/uaccess.h> +#include <asm/plat-s3c24xx/neo1973.h> +#include <asm/arch/gta02.h> /* * Architectures can override it: @@ -67,6 +71,12 @@ int console_printk[4] = { int oops_in_progress; EXPORT_SYMBOL(oops_in_progress); +void (*printk_emergency_debug_spew_init)(void) = NULL; +EXPORT_SYMBOL(printk_emergency_debug_spew_init); + +void (*printk_emergency_debug_spew_send_string)(const char *) = NULL; +EXPORT_SYMBOL(printk_emergency_debug_spew_send_string); + /* * console_sem protects the console_drivers list, and also * provides serialisation for access to the entire console @@ -668,6 +678,37 @@ asmlinkage int vprintk(const char *fmt, va_list args) printed_len += vscnprintf(printk_buf + printed_len, sizeof(printk_buf) - printed_len, fmt, args); + /* if you're debugging resume, the normal methods can change resume + * ordering behaviours because their debugging output is synchronous + * (ie, CONFIG_DEBUG_LL). If your problem is an OOPS, this code + * will not affect the speed and duration and ordering of resume + * actions, but will give you a chance to read the full undumped + * syslog AND the OOPS data when it happens + * + * if you support it, your debug device init can override the exported + * emergency_debug_spew_init and emergency_debug_spew_send_string to + * usually force polling or bitbanging on your debug console device + */ + if (oops_in_progress && global_inside_suspend && + printk_emergency_debug_spew_init && + printk_emergency_debug_spew_send_string) { + unsigned long cur_index; + char ch[2]; + + if (global_inside_suspend == 1) { + (printk_emergency_debug_spew_init)(); + + ch[1] = '\0'; + cur_index = con_start; + while (cur_index != log_end) { + ch[0] = LOG_BUF(cur_index); + (printk_emergency_debug_spew_send_string)(ch); + cur_index++; + } + global_inside_suspend++; /* only once */ + } + (printk_emergency_debug_spew_send_string)(printk_buf); + } /* * Copy the output into log_buf. If the caller didn't provide |