1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/kernel.h>
20#include <linux/mm.h>
21#include <linux/tty.h>
22#include <linux/tty_driver.h>
23#include <linux/console.h>
24#include <linux/init.h>
25#include <linux/jiffies.h>
26#include <linux/nmi.h>
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <linux/smp.h>
32#include <linux/security.h>
33#include <linux/bootmem.h>
34#include <linux/syscalls.h>
35#include <linux/kexec.h>
36
37#include <asm/uaccess.h>
38
39
40
41
42void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
43{
44}
45
46#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
47
48
49#define DEFAULT_MESSAGE_LOGLEVEL 4
50
51
52#define MINIMUM_CONSOLE_LOGLEVEL 1
53#define DEFAULT_CONSOLE_LOGLEVEL 7
54
55DECLARE_WAIT_QUEUE_HEAD(log_wait);
56
57int console_printk[4] = {
58 DEFAULT_CONSOLE_LOGLEVEL,
59 DEFAULT_MESSAGE_LOGLEVEL,
60 MINIMUM_CONSOLE_LOGLEVEL,
61 DEFAULT_CONSOLE_LOGLEVEL,
62};
63
64
65
66
67
68int oops_in_progress;
69EXPORT_SYMBOL(oops_in_progress);
70
71
72
73
74
75
76static DECLARE_MUTEX(console_sem);
77struct console *console_drivers;
78EXPORT_SYMBOL_GPL(console_drivers);
79
80
81
82
83
84
85
86
87
88static int console_locked, console_suspended;
89
90
91
92
93
94
95static DEFINE_SPINLOCK(logbuf_lock);
96
97#define LOG_BUF_MASK (log_buf_len-1)
98#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
99
100
101
102
103
104static unsigned log_start;
105static unsigned con_start;
106static unsigned log_end;
107
108
109
110
111struct console_cmdline
112{
113 char name[8];
114 int index;
115 char *options;
116#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
117 char *brl_options;
118#endif
119};
120
121#define MAX_CMDLINECONSOLES 8
122
123static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
124static int selected_console = -1;
125static int preferred_console = -1;
126int console_set_on_cmdline;
127EXPORT_SYMBOL(console_set_on_cmdline);
128
129
130static int console_may_schedule;
131
132#ifdef CONFIG_PRINTK
133
134static char __log_buf[__LOG_BUF_LEN];
135static char *log_buf = __log_buf;
136static int log_buf_len = __LOG_BUF_LEN;
137static unsigned logged_chars;
138
139#ifdef CONFIG_KEXEC
140
141
142
143
144
145
146
147
148void log_buf_kexec_setup(void)
149{
150 VMCOREINFO_SYMBOL(log_buf);
151 VMCOREINFO_SYMBOL(log_end);
152 VMCOREINFO_SYMBOL(log_buf_len);
153 VMCOREINFO_SYMBOL(logged_chars);
154}
155#endif
156
157static int __init log_buf_len_setup(char *str)
158{
159 unsigned size = memparse(str, &str);
160 unsigned long flags;
161
162 if (size)
163 size = roundup_pow_of_two(size);
164 if (size > log_buf_len) {
165 unsigned start, dest_idx, offset;
166 char *new_log_buf;
167
168 new_log_buf = alloc_bootmem(size);
169 if (!new_log_buf) {
170 printk(KERN_WARNING "log_buf_len: allocation failed\n");
171 goto out;
172 }
173
174 spin_lock_irqsave(&logbuf_lock, flags);
175 log_buf_len = size;
176 log_buf = new_log_buf;
177
178 offset = start = min(con_start, log_start);
179 dest_idx = 0;
180 while (start != log_end) {
181 log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)];
182 start++;
183 dest_idx++;
184 }
185 log_start -= offset;
186 con_start -= offset;
187 log_end -= offset;
188 spin_unlock_irqrestore(&logbuf_lock, flags);
189
190 printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
191 }
192out:
193 return 1;
194}
195
196__setup("log_buf_len=", log_buf_len_setup);
197
198#ifdef CONFIG_BOOT_PRINTK_DELAY
199
200static unsigned int boot_delay;
201static unsigned long long printk_delay_msec;
202
203static int __init boot_delay_setup(char *str)
204{
205 unsigned long lpj;
206 unsigned long long loops_per_msec;
207
208 lpj = preset_lpj ? preset_lpj : 1000000;
209 loops_per_msec = (unsigned long long)lpj / 1000 * HZ;
210
211 get_option(&str, &boot_delay);
212 if (boot_delay > 10 * 1000)
213 boot_delay = 0;
214
215 printk_delay_msec = loops_per_msec;
216 printk(KERN_DEBUG "boot_delay: %u, preset_lpj: %ld, lpj: %lu, "
217 "HZ: %d, printk_delay_msec: %llu\n",
218 boot_delay, preset_lpj, lpj, HZ, printk_delay_msec);
219 return 1;
220}
221__setup("boot_delay=", boot_delay_setup);
222
223static void boot_delay_msec(void)
224{
225 unsigned long long k;
226 unsigned long timeout;
227
228 if (boot_delay == 0 || system_state != SYSTEM_BOOTING)
229 return;
230
231 k = (unsigned long long)printk_delay_msec * boot_delay;
232
233 timeout = jiffies + msecs_to_jiffies(boot_delay);
234 while (k) {
235 k--;
236 cpu_relax();
237
238
239
240
241
242 if (time_after(jiffies, timeout))
243 break;
244 touch_nmi_watchdog();
245 }
246}
247#else
248static inline void boot_delay_msec(void)
249{
250}
251#endif
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268int do_syslog(int type, char __user *buf, int len)
269{
270 unsigned i, j, limit, count;
271 int do_clear = 0;
272 char c;
273 int error = 0;
274
275 error = security_syslog(type);
276 if (error)
277 return error;
278
279 switch (type) {
280 case 0:
281 break;
282 case 1:
283 break;
284 case 2:
285 error = -EINVAL;
286 if (!buf || len < 0)
287 goto out;
288 error = 0;
289 if (!len)
290 goto out;
291 if (!access_ok(VERIFY_WRITE, buf, len)) {
292 error = -EFAULT;
293 goto out;
294 }
295 error = wait_event_interruptible(log_wait,
296 (log_start - log_end));
297 if (error)
298 goto out;
299 i = 0;
300 spin_lock_irq(&logbuf_lock);
301 while (!error && (log_start != log_end) && i < len) {
302 c = LOG_BUF(log_start);
303 log_start++;
304 spin_unlock_irq(&logbuf_lock);
305 error = __put_user(c,buf);
306 buf++;
307 i++;
308 cond_resched();
309 spin_lock_irq(&logbuf_lock);
310 }
311 spin_unlock_irq(&logbuf_lock);
312 if (!error)
313 error = i;
314 break;
315 case 4:
316 do_clear = 1;
317
318 case 3:
319 error = -EINVAL;
320 if (!buf || len < 0)
321 goto out;
322 error = 0;
323 if (!len)
324 goto out;
325 if (!access_ok(VERIFY_WRITE, buf, len)) {
326 error = -EFAULT;
327 goto out;
328 }
329 count = len;
330 if (count > log_buf_len)
331 count = log_buf_len;
332 spin_lock_irq(&logbuf_lock);
333 if (count > logged_chars)
334 count = logged_chars;
335 if (do_clear)
336 logged_chars = 0;
337 limit = log_end;
338
339
340
341
342
343
344 for (i = 0; i < count && !error; i++) {
345 j = limit-1-i;
346 if (j + log_buf_len < log_end)
347 break;
348 c = LOG_BUF(j);
349 spin_unlock_irq(&logbuf_lock);
350 error = __put_user(c,&buf[count-1-i]);
351 cond_resched();
352 spin_lock_irq(&logbuf_lock);
353 }
354 spin_unlock_irq(&logbuf_lock);
355 if (error)
356 break;
357 error = i;
358 if (i != count) {
359 int offset = count-error;
360
361 for (i = 0; i < error; i++) {
362 if (__get_user(c,&buf[i+offset]) ||
363 __put_user(c,&buf[i])) {
364 error = -EFAULT;
365 break;
366 }
367 cond_resched();
368 }
369 }
370 break;
371 case 5:
372 logged_chars = 0;
373 break;
374 case 6:
375 console_loglevel = minimum_console_loglevel;
376 break;
377 case 7:
378 console_loglevel = default_console_loglevel;
379 break;
380 case 8:
381 error = -EINVAL;
382 if (len < 1 || len > 8)
383 goto out;
384 if (len < minimum_console_loglevel)
385 len = minimum_console_loglevel;
386 console_loglevel = len;
387 error = 0;
388 break;
389 case 9:
390 error = log_end - log_start;
391 break;
392 case 10:
393 error = log_buf_len;
394 break;
395 default:
396 error = -EINVAL;
397 break;
398 }
399out:
400 return error;
401}
402
403SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
404{
405 return do_syslog(type, buf, len);
406}
407
408
409
410
411static void __call_console_drivers(unsigned start, unsigned end)
412{
413 struct console *con;
414
415 for (con = console_drivers; con; con = con->next) {
416 if ((con->flags & CON_ENABLED) && con->write &&
417 (cpu_online(smp_processor_id()) ||
418 (con->flags & CON_ANYTIME)))
419 con->write(con, &LOG_BUF(start), end - start);
420 }
421}
422
423static int __read_mostly ignore_loglevel;
424
425static int __init ignore_loglevel_setup(char *str)
426{
427 ignore_loglevel = 1;
428 printk(KERN_INFO "debug: ignoring loglevel setting.\n");
429
430 return 0;
431}
432
433early_param("ignore_loglevel", ignore_loglevel_setup);
434
435
436
437
438static void _call_console_drivers(unsigned start,
439 unsigned end, int msg_log_level)
440{
441 if ((msg_log_level < console_loglevel || ignore_loglevel) &&
442 console_drivers && start != end) {
443 if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
444
445 __call_console_drivers(start & LOG_BUF_MASK,
446 log_buf_len);
447 __call_console_drivers(0, end & LOG_BUF_MASK);
448 } else {
449 __call_console_drivers(start, end);
450 }
451 }
452}
453
454
455
456
457
458
459static void call_console_drivers(unsigned start, unsigned end)
460{
461 unsigned cur_index, start_print;
462 static int msg_level = -1;
463
464 BUG_ON(((int)(start - end)) > 0);
465
466 cur_index = start;
467 start_print = start;
468 while (cur_index != end) {
469 if (msg_level < 0 && ((end - cur_index) > 2) &&
470 LOG_BUF(cur_index + 0) == '<' &&
471 LOG_BUF(cur_index + 1) >= '0' &&
472 LOG_BUF(cur_index + 1) <= '7' &&
473 LOG_BUF(cur_index + 2) == '>') {
474 msg_level = LOG_BUF(cur_index + 1) - '0';
475 cur_index += 3;
476 start_print = cur_index;
477 }
478 while (cur_index != end) {
479 char c = LOG_BUF(cur_index);
480
481 cur_index++;
482 if (c == '\n') {
483 if (msg_level < 0) {
484
485
486
487
488
489
490 msg_level = default_message_loglevel;
491 }
492 _call_console_drivers(start_print, cur_index, msg_level);
493 msg_level = -1;
494 start_print = cur_index;
495 break;
496 }
497 }
498 }
499 _call_console_drivers(start_print, end, msg_level);
500}
501
502static void emit_log_char(char c)
503{
504 LOG_BUF(log_end) = c;
505 log_end++;
506 if (log_end - log_start > log_buf_len)
507 log_start = log_end - log_buf_len;
508 if (log_end - con_start > log_buf_len)
509 con_start = log_end - log_buf_len;
510 if (logged_chars < log_buf_len)
511 logged_chars++;
512}
513
514
515
516
517
518
519static void zap_locks(void)
520{
521 static unsigned long oops_timestamp;
522
523 if (time_after_eq(jiffies, oops_timestamp) &&
524 !time_after(jiffies, oops_timestamp + 30 * HZ))
525 return;
526
527 oops_timestamp = jiffies;
528
529
530 spin_lock_init(&logbuf_lock);
531
532 init_MUTEX(&console_sem);
533}
534
535#if defined(CONFIG_PRINTK_TIME)
536static int printk_time = 1;
537#else
538static int printk_time = 0;
539#endif
540module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
541
542
543static int have_callable_console(void)
544{
545 struct console *con;
546
547 for (con = console_drivers; con; con = con->next)
548 if (con->flags & CON_ANYTIME)
549 return 1;
550
551 return 0;
552}
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576asmlinkage int printk(const char *fmt, ...)
577{
578 va_list args;
579 int r;
580
581 va_start(args, fmt);
582 r = vprintk(fmt, args);
583 va_end(args);
584
585 return r;
586}
587
588
589static volatile unsigned int printk_cpu = UINT_MAX;
590
591
592
593
594
595
596
597
598
599static inline int can_use_console(unsigned int cpu)
600{
601 return cpu_online(cpu) || have_callable_console();
602}
603
604
605
606
607
608
609
610
611
612
613
614static int acquire_console_semaphore_for_printk(unsigned int cpu)
615{
616 int retval = 0;
617
618 if (!try_acquire_console_sem()) {
619 retval = 1;
620
621
622
623
624
625
626
627 if (!can_use_console(cpu)) {
628 console_locked = 0;
629 up(&console_sem);
630 retval = 0;
631 }
632 }
633 printk_cpu = UINT_MAX;
634 spin_unlock(&logbuf_lock);
635 return retval;
636}
637static const char recursion_bug_msg [] =
638 KERN_CRIT "BUG: recent printk recursion!\n";
639static int recursion_bug;
640static int new_text_line = 1;
641static char printk_buf[1024];
642
643asmlinkage int vprintk(const char *fmt, va_list args)
644{
645 int printed_len = 0;
646 int current_log_level = default_message_loglevel;
647 unsigned long flags;
648 int this_cpu;
649 char *p;
650
651 boot_delay_msec();
652
653 preempt_disable();
654
655 raw_local_irq_save(flags);
656 this_cpu = smp_processor_id();
657
658
659
660
661 if (unlikely(printk_cpu == this_cpu)) {
662
663
664
665
666
667
668
669 if (!oops_in_progress) {
670 recursion_bug = 1;
671 goto out_restore_irqs;
672 }
673 zap_locks();
674 }
675
676 lockdep_off();
677 spin_lock(&logbuf_lock);
678 printk_cpu = this_cpu;
679
680 if (recursion_bug) {
681 recursion_bug = 0;
682 strcpy(printk_buf, recursion_bug_msg);
683 printed_len = strlen(recursion_bug_msg);
684 }
685
686 printed_len += vscnprintf(printk_buf + printed_len,
687 sizeof(printk_buf) - printed_len, fmt, args);
688
689
690
691
692
693
694 for (p = printk_buf; *p; p++) {
695 if (new_text_line) {
696
697 if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&
698 p[2] == '>') {
699 current_log_level = p[1] - '0';
700 p += 3;
701 printed_len -= 3;
702 }
703
704
705 emit_log_char('<');
706 emit_log_char(current_log_level + '0');
707 emit_log_char('>');
708 printed_len += 3;
709 new_text_line = 0;
710
711 if (printk_time) {
712
713 char tbuf[50], *tp;
714 unsigned tlen;
715 unsigned long long t;
716 unsigned long nanosec_rem;
717
718 t = cpu_clock(printk_cpu);
719 nanosec_rem = do_div(t, 1000000000);
720 tlen = sprintf(tbuf, "[%5lu.%06lu] ",
721 (unsigned long) t,
722 nanosec_rem / 1000);
723
724 for (tp = tbuf; tp < tbuf + tlen; tp++)
725 emit_log_char(*tp);
726 printed_len += tlen;
727 }
728
729 if (!*p)
730 break;
731 }
732
733 emit_log_char(*p);
734 if (*p == '\n')
735 new_text_line = 1;
736 }
737
738
739
740
741
742
743
744
745
746
747
748 if (acquire_console_semaphore_for_printk(this_cpu))
749 release_console_sem();
750
751 lockdep_on();
752out_restore_irqs:
753 raw_local_irq_restore(flags);
754
755 preempt_enable();
756 return printed_len;
757}
758EXPORT_SYMBOL(printk);
759EXPORT_SYMBOL(vprintk);
760
761#else
762
763static void call_console_drivers(unsigned start, unsigned end)
764{
765}
766
767#endif
768
769static int __add_preferred_console(char *name, int idx, char *options,
770 char *brl_options)
771{
772 struct console_cmdline *c;
773 int i;
774
775
776
777
778
779 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
780 if (strcmp(console_cmdline[i].name, name) == 0 &&
781 console_cmdline[i].index == idx) {
782 if (!brl_options)
783 selected_console = i;
784 return 0;
785 }
786 if (i == MAX_CMDLINECONSOLES)
787 return -E2BIG;
788 if (!brl_options)
789 selected_console = i;
790 c = &console_cmdline[i];
791 strlcpy(c->name, name, sizeof(c->name));
792 c->options = options;
793#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
794 c->brl_options = brl_options;
795#endif
796 c->index = idx;
797 return 0;
798}
799
800
801
802static int __init console_setup(char *str)
803{
804 char buf[sizeof(console_cmdline[0].name) + 4];
805 char *s, *options, *brl_options = NULL;
806 int idx;
807
808#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
809 if (!memcmp(str, "brl,", 4)) {
810 brl_options = "";
811 str += 4;
812 } else if (!memcmp(str, "brl=", 4)) {
813 brl_options = str + 4;
814 str = strchr(brl_options, ',');
815 if (!str) {
816 printk(KERN_ERR "need port name after brl=\n");
817 return 1;
818 }
819 *(str++) = 0;
820 }
821#endif
822
823
824
825
826 if (str[0] >= '0' && str[0] <= '9') {
827 strcpy(buf, "ttyS");
828 strncpy(buf + 4, str, sizeof(buf) - 5);
829 } else {
830 strncpy(buf, str, sizeof(buf) - 1);
831 }
832 buf[sizeof(buf) - 1] = 0;
833 if ((options = strchr(str, ',')) != NULL)
834 *(options++) = 0;
835#ifdef __sparc__
836 if (!strcmp(str, "ttya"))
837 strcpy(buf, "ttyS0");
838 if (!strcmp(str, "ttyb"))
839 strcpy(buf, "ttyS1");
840#endif
841 for (s = buf; *s; s++)
842 if ((*s >= '0' && *s <= '9') || *s == ',')
843 break;
844 idx = simple_strtoul(s, NULL, 10);
845 *s = 0;
846
847 __add_preferred_console(buf, idx, options, brl_options);
848 console_set_on_cmdline = 1;
849 return 1;
850}
851__setup("console=", console_setup);
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866int add_preferred_console(char *name, int idx, char *options)
867{
868 return __add_preferred_console(name, idx, options, NULL);
869}
870
871int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
872{
873 struct console_cmdline *c;
874 int i;
875
876 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
877 if (strcmp(console_cmdline[i].name, name) == 0 &&
878 console_cmdline[i].index == idx) {
879 c = &console_cmdline[i];
880 strlcpy(c->name, name_new, sizeof(c->name));
881 c->name[sizeof(c->name) - 1] = 0;
882 c->options = options;
883 c->index = idx_new;
884 return i;
885 }
886
887 return -1;
888}
889
890int console_suspend_enabled = 1;
891EXPORT_SYMBOL(console_suspend_enabled);
892
893static int __init console_suspend_disable(char *str)
894{
895 console_suspend_enabled = 0;
896 return 1;
897}
898__setup("no_console_suspend", console_suspend_disable);
899
900
901
902
903
904
905void suspend_console(void)
906{
907 if (!console_suspend_enabled)
908 return;
909 printk("Suspending console(s) (use no_console_suspend to debug)\n");
910 acquire_console_sem();
911 console_suspended = 1;
912 up(&console_sem);
913}
914
915void resume_console(void)
916{
917 if (!console_suspend_enabled)
918 return;
919 down(&console_sem);
920 console_suspended = 0;
921 release_console_sem();
922}
923
924
925
926
927
928
929
930
931
932void acquire_console_sem(void)
933{
934 BUG_ON(in_interrupt());
935 down(&console_sem);
936 if (console_suspended)
937 return;
938 console_locked = 1;
939 console_may_schedule = 1;
940}
941EXPORT_SYMBOL(acquire_console_sem);
942
943int try_acquire_console_sem(void)
944{
945 if (down_trylock(&console_sem))
946 return -1;
947 if (console_suspended) {
948 up(&console_sem);
949 return -1;
950 }
951 console_locked = 1;
952 console_may_schedule = 0;
953 return 0;
954}
955EXPORT_SYMBOL(try_acquire_console_sem);
956
957int is_console_locked(void)
958{
959 return console_locked;
960}
961
962static DEFINE_PER_CPU(int, printk_pending);
963
964void printk_tick(void)
965{
966 if (__get_cpu_var(printk_pending)) {
967 __get_cpu_var(printk_pending) = 0;
968 wake_up_interruptible(&log_wait);
969 }
970}
971
972int printk_needs_cpu(int cpu)
973{
974 return per_cpu(printk_pending, cpu);
975}
976
977void wake_up_klogd(void)
978{
979 if (waitqueue_active(&log_wait))
980 __raw_get_cpu_var(printk_pending) = 1;
981}
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997void release_console_sem(void)
998{
999 unsigned long flags;
1000 unsigned _con_start, _log_end;
1001 unsigned wake_klogd = 0;
1002
1003 if (console_suspended) {
1004 up(&console_sem);
1005 return;
1006 }
1007
1008 console_may_schedule = 0;
1009
1010 for ( ; ; ) {
1011 spin_lock_irqsave(&logbuf_lock, flags);
1012 wake_klogd |= log_start - log_end;
1013 if (con_start == log_end)
1014 break;
1015 _con_start = con_start;
1016 _log_end = log_end;
1017 con_start = log_end;
1018 spin_unlock(&logbuf_lock);
1019 stop_critical_timings();
1020 call_console_drivers(_con_start, _log_end);
1021 start_critical_timings();
1022 local_irq_restore(flags);
1023 }
1024 console_locked = 0;
1025 up(&console_sem);
1026 spin_unlock_irqrestore(&logbuf_lock, flags);
1027 if (wake_klogd)
1028 wake_up_klogd();
1029}
1030EXPORT_SYMBOL(release_console_sem);
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041void __sched console_conditional_schedule(void)
1042{
1043 if (console_may_schedule)
1044 cond_resched();
1045}
1046EXPORT_SYMBOL(console_conditional_schedule);
1047
1048void console_print(const char *s)
1049{
1050 printk(KERN_EMERG "%s", s);
1051}
1052EXPORT_SYMBOL(console_print);
1053
1054void console_unblank(void)
1055{
1056 struct console *c;
1057
1058
1059
1060
1061
1062 if (oops_in_progress) {
1063 if (down_trylock(&console_sem) != 0)
1064 return;
1065 } else
1066 acquire_console_sem();
1067
1068 console_locked = 1;
1069 console_may_schedule = 0;
1070 for (c = console_drivers; c != NULL; c = c->next)
1071 if ((c->flags & CON_ENABLED) && c->unblank)
1072 c->unblank();
1073 release_console_sem();
1074}
1075
1076
1077
1078
1079struct tty_driver *console_device(int *index)
1080{
1081 struct console *c;
1082 struct tty_driver *driver = NULL;
1083
1084 acquire_console_sem();
1085 for (c = console_drivers; c != NULL; c = c->next) {
1086 if (!c->device)
1087 continue;
1088 driver = c->device(c, index);
1089 if (driver)
1090 break;
1091 }
1092 release_console_sem();
1093 return driver;
1094}
1095
1096
1097
1098
1099
1100
1101void console_stop(struct console *console)
1102{
1103 acquire_console_sem();
1104 console->flags &= ~CON_ENABLED;
1105 release_console_sem();
1106}
1107EXPORT_SYMBOL(console_stop);
1108
1109void console_start(struct console *console)
1110{
1111 acquire_console_sem();
1112 console->flags |= CON_ENABLED;
1113 release_console_sem();
1114}
1115EXPORT_SYMBOL(console_start);
1116
1117
1118
1119
1120
1121
1122
1123void register_console(struct console *console)
1124{
1125 int i;
1126 unsigned long flags;
1127 struct console *bootconsole = NULL;
1128
1129 if (console_drivers) {
1130 if (console->flags & CON_BOOT)
1131 return;
1132 if (console_drivers->flags & CON_BOOT)
1133 bootconsole = console_drivers;
1134 }
1135
1136 if (preferred_console < 0 || bootconsole || !console_drivers)
1137 preferred_console = selected_console;
1138
1139 if (console->early_setup)
1140 console->early_setup();
1141
1142
1143
1144
1145
1146
1147 if (preferred_console < 0) {
1148 if (console->index < 0)
1149 console->index = 0;
1150 if (console->setup == NULL ||
1151 console->setup(console, NULL) == 0) {
1152 console->flags |= CON_ENABLED;
1153 if (console->device) {
1154 console->flags |= CON_CONSDEV;
1155 preferred_console = 0;
1156 }
1157 }
1158 }
1159
1160
1161
1162
1163
1164 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
1165 i++) {
1166 if (strcmp(console_cmdline[i].name, console->name) != 0)
1167 continue;
1168 if (console->index >= 0 &&
1169 console->index != console_cmdline[i].index)
1170 continue;
1171 if (console->index < 0)
1172 console->index = console_cmdline[i].index;
1173#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
1174 if (console_cmdline[i].brl_options) {
1175 console->flags |= CON_BRL;
1176 braille_register_console(console,
1177 console_cmdline[i].index,
1178 console_cmdline[i].options,
1179 console_cmdline[i].brl_options);
1180 return;
1181 }
1182#endif
1183 if (console->setup &&
1184 console->setup(console, console_cmdline[i].options) != 0)
1185 break;
1186 console->flags |= CON_ENABLED;
1187 console->index = console_cmdline[i].index;
1188 if (i == selected_console) {
1189 console->flags |= CON_CONSDEV;
1190 preferred_console = selected_console;
1191 }
1192 break;
1193 }
1194
1195 if (!(console->flags & CON_ENABLED))
1196 return;
1197
1198 if (bootconsole && (console->flags & CON_CONSDEV)) {
1199 printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
1200 bootconsole->name, bootconsole->index,
1201 console->name, console->index);
1202 unregister_console(bootconsole);
1203 console->flags &= ~CON_PRINTBUFFER;
1204 } else {
1205 printk(KERN_INFO "console [%s%d] enabled\n",
1206 console->name, console->index);
1207 }
1208
1209
1210
1211
1212
1213 acquire_console_sem();
1214 if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
1215 console->next = console_drivers;
1216 console_drivers = console;
1217 if (console->next)
1218 console->next->flags &= ~CON_CONSDEV;
1219 } else {
1220 console->next = console_drivers->next;
1221 console_drivers->next = console;
1222 }
1223 if (console->flags & CON_PRINTBUFFER) {
1224
1225
1226
1227
1228 spin_lock_irqsave(&logbuf_lock, flags);
1229 con_start = log_start;
1230 spin_unlock_irqrestore(&logbuf_lock, flags);
1231 }
1232 release_console_sem();
1233}
1234EXPORT_SYMBOL(register_console);
1235
1236int unregister_console(struct console *console)
1237{
1238 struct console *a, *b;
1239 int res = 1;
1240
1241#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
1242 if (console->flags & CON_BRL)
1243 return braille_unregister_console(console);
1244#endif
1245
1246 acquire_console_sem();
1247 if (console_drivers == console) {
1248 console_drivers=console->next;
1249 res = 0;
1250 } else if (console_drivers) {
1251 for (a=console_drivers->next, b=console_drivers ;
1252 a; b=a, a=b->next) {
1253 if (a == console) {
1254 b->next = a->next;
1255 res = 0;
1256 break;
1257 }
1258 }
1259 }
1260
1261
1262
1263
1264
1265 if (console_drivers != NULL && console->flags & CON_CONSDEV)
1266 console_drivers->flags |= CON_CONSDEV;
1267
1268 release_console_sem();
1269 return res;
1270}
1271EXPORT_SYMBOL(unregister_console);
1272
1273static int __init disable_boot_consoles(void)
1274{
1275 if (console_drivers != NULL) {
1276 if (console_drivers->flags & CON_BOOT) {
1277 printk(KERN_INFO "turn off boot console %s%d\n",
1278 console_drivers->name, console_drivers->index);
1279 return unregister_console(console_drivers);
1280 }
1281 }
1282 return 0;
1283}
1284late_initcall(disable_boot_consoles);
1285
1286#if defined CONFIG_PRINTK
1287
1288
1289
1290
1291
1292
1293
1294DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
1295
1296int printk_ratelimit(void)
1297{
1298 return __ratelimit(&printk_ratelimit_state);
1299}
1300EXPORT_SYMBOL(printk_ratelimit);
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311bool printk_timed_ratelimit(unsigned long *caller_jiffies,
1312 unsigned int interval_msecs)
1313{
1314 if (*caller_jiffies == 0
1315 || !time_in_range(jiffies, *caller_jiffies,
1316 *caller_jiffies
1317 + msecs_to_jiffies(interval_msecs))) {
1318 *caller_jiffies = jiffies;
1319 return true;
1320 }
1321 return false;
1322}
1323EXPORT_SYMBOL(printk_timed_ratelimit);
1324#endif
1325