aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c127
1 files changed, 125 insertions, 2 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 8451dfc31d25..a30fe33de395 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -22,6 +22,8 @@
22#include <linux/tty_driver.h> 22#include <linux/tty_driver.h>
23#include <linux/console.h> 23#include <linux/console.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/jiffies.h>
26#include <linux/nmi.h>
25#include <linux/module.h> 27#include <linux/module.h>
26#include <linux/moduleparam.h> 28#include <linux/moduleparam.h>
27#include <linux/interrupt.h> /* For in_interrupt() */ 29#include <linux/interrupt.h> /* For in_interrupt() */
@@ -162,6 +164,113 @@ out:
162 164
163__setup("log_buf_len=", log_buf_len_setup); 165__setup("log_buf_len=", log_buf_len_setup);
164 166
167#ifdef CONFIG_BOOT_PRINTK_DELAY
168
169static unsigned int boot_delay; /* msecs delay after each printk during bootup */
170static unsigned long long printk_delay_msec; /* per msec, based on boot_delay */
171
172static int __init boot_delay_setup(char *str)
173{
174 unsigned long lpj;
175 unsigned long long loops_per_msec;
176
177 lpj = preset_lpj ? preset_lpj : 1000000; /* some guess */
178 loops_per_msec = (unsigned long long)lpj / 1000 * HZ;
179
180 get_option(&str, &boot_delay);
181 if (boot_delay > 10 * 1000)
182 boot_delay = 0;
183
184 printk_delay_msec = loops_per_msec;
185 printk(KERN_DEBUG "boot_delay: %u, preset_lpj: %ld, lpj: %lu, "
186 "HZ: %d, printk_delay_msec: %llu\n",
187 boot_delay, preset_lpj, lpj, HZ, printk_delay_msec);
188 return 1;
189}
190__setup("boot_delay=", boot_delay_setup);
191
192static void boot_delay_msec(void)
193{
194 unsigned long long k;
195 unsigned long timeout;
196
197 if (boot_delay == 0 || system_state != SYSTEM_BOOTING)
198 return;
199
200 k = (unsigned long long)printk_delay_msec * boot_delay;
201
202 timeout = jiffies + msecs_to_jiffies(boot_delay);
203 while (k) {
204 k--;
205 cpu_relax();
206 /*
207 * use (volatile) jiffies to prevent
208 * compiler reduction; loop termination via jiffies
209 * is secondary and may or may not happen.
210 */
211 if (time_after(jiffies, timeout))
212 break;
213 touch_nmi_watchdog();
214 }
215}
216#else
217static inline void boot_delay_msec(void)
218{
219}
220#endif
221
222/*
223 * Return the number of unread characters in the log buffer.
224 */
225int log_buf_get_len(void)
226{
227 return logged_chars;
228}
229
230/*
231 * Copy a range of characters from the log buffer.
232 */
233int log_buf_copy(char *dest, int idx, int len)
234{
235 int ret, max;
236 bool took_lock = false;
237
238 if (!oops_in_progress) {
239 spin_lock_irq(&logbuf_lock);
240 took_lock = true;
241 }
242
243 max = log_buf_get_len();
244 if (idx < 0 || idx >= max) {
245 ret = -1;
246 } else {
247 if (len > max)
248 len = max;
249 ret = len;
250 idx += (log_end - max);
251 while (len-- > 0)
252 dest[len] = LOG_BUF(idx + len);
253 }
254
255 if (took_lock)
256 spin_unlock_irq(&logbuf_lock);
257
258 return ret;
259}
260
261/*
262 * Extract a single character from the log buffer.
263 */
264int log_buf_read(int idx)
265{
266 char ret;
267
268 if (log_buf_copy(&ret, idx, 1) == 1)
269 return ret;
270 else
271 return -1;
272}
273
165/* 274/*
166 * Commands to do_syslog: 275 * Commands to do_syslog:
167 * 276 *
@@ -527,6 +636,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
527 static char printk_buf[1024]; 636 static char printk_buf[1024];
528 static int log_level_unknown = 1; 637 static int log_level_unknown = 1;
529 638
639 boot_delay_msec();
640
530 preempt_disable(); 641 preempt_disable();
531 if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) 642 if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
532 /* If a crash is occurring during printk() on this CPU, 643 /* If a crash is occurring during printk() on this CPU,
@@ -751,7 +862,16 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
751 return -1; 862 return -1;
752} 863}
753 864
754#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND 865int console_suspend_enabled = 1;
866EXPORT_SYMBOL(console_suspend_enabled);
867
868static int __init console_suspend_disable(char *str)
869{
870 console_suspend_enabled = 0;
871 return 1;
872}
873__setup("no_console_suspend", console_suspend_disable);
874
755/** 875/**
756 * suspend_console - suspend the console subsystem 876 * suspend_console - suspend the console subsystem
757 * 877 *
@@ -759,6 +879,8 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
759 */ 879 */
760void suspend_console(void) 880void suspend_console(void)
761{ 881{
882 if (!console_suspend_enabled)
883 return;
762 printk("Suspending console(s)\n"); 884 printk("Suspending console(s)\n");
763 acquire_console_sem(); 885 acquire_console_sem();
764 console_suspended = 1; 886 console_suspended = 1;
@@ -766,10 +888,11 @@ void suspend_console(void)
766 888
767void resume_console(void) 889void resume_console(void)
768{ 890{
891 if (!console_suspend_enabled)
892 return;
769 console_suspended = 0; 893 console_suspended = 0;
770 release_console_sem(); 894 release_console_sem();
771} 895}
772#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
773 896
774/** 897/**
775 * acquire_console_sem - lock the console system for exclusive use. 898 * acquire_console_sem - lock the console system for exclusive use.