1 |
1275 |
phoenix |
/*
|
2 |
|
|
* linux/kernel/printk.c
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
5 |
|
|
*
|
6 |
|
|
* Modified to make sys_syslog() more flexible: added commands to
|
7 |
|
|
* return the last 4k of kernel messages, regardless of whether
|
8 |
|
|
* they've been read or not. Added option to suppress kernel printk's
|
9 |
|
|
* to the console. Added hook for sending the console messages
|
10 |
|
|
* elsewhere, in preparation for a serial line console (someday).
|
11 |
|
|
* Ted Ts'o, 2/11/93.
|
12 |
|
|
* Modified for sysctl support, 1/8/97, Chris Horn.
|
13 |
|
|
* Fixed SMP synchronization, 08/08/99, Manfred Spraul
|
14 |
|
|
* manfreds@colorfullife.com
|
15 |
|
|
* Rewrote bits to get rid of console_lock
|
16 |
|
|
* 01Mar01 Andrew Morton <andrewm@uow.edu.au>
|
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/smp_lock.h>
|
24 |
|
|
#include <linux/console.h>
|
25 |
|
|
#include <linux/init.h>
|
26 |
|
|
#include <linux/module.h>
|
27 |
|
|
#include <linux/interrupt.h> /* For in_interrupt() */
|
28 |
|
|
#include <linux/config.h>
|
29 |
|
|
|
30 |
|
|
#include <asm/uaccess.h>
|
31 |
|
|
|
32 |
|
|
#if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
|
33 |
|
|
#if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
|
34 |
|
|
#define LOG_BUF_LEN (65536)
|
35 |
|
|
#elif defined(CONFIG_ARCH_S390)
|
36 |
|
|
#define LOG_BUF_LEN (131072)
|
37 |
|
|
#elif defined(CONFIG_SMP)
|
38 |
|
|
#define LOG_BUF_LEN (32768)
|
39 |
|
|
#else
|
40 |
|
|
#define LOG_BUF_LEN (16384) /* This must be a power of two */
|
41 |
|
|
#endif
|
42 |
|
|
#else /* CONFIG_LOG_BUF_SHIFT */
|
43 |
|
|
#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
|
44 |
|
|
#endif
|
45 |
|
|
|
46 |
|
|
#define LOG_BUF_MASK (LOG_BUF_LEN-1)
|
47 |
|
|
|
48 |
|
|
#ifndef arch_consoles_callable
|
49 |
|
|
#define arch_consoles_callable() (1)
|
50 |
|
|
#endif
|
51 |
|
|
|
52 |
|
|
/* printk's without a loglevel use this.. */
|
53 |
|
|
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
|
54 |
|
|
|
55 |
|
|
/* We show everything that is MORE important than this.. */
|
56 |
|
|
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
|
57 |
|
|
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
|
58 |
|
|
|
59 |
|
|
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
60 |
|
|
|
61 |
|
|
int console_printk[4] = {
|
62 |
|
|
DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
|
63 |
|
|
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
|
64 |
|
|
MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */
|
65 |
|
|
DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
|
66 |
|
|
};
|
67 |
|
|
|
68 |
|
|
int oops_in_progress;
|
69 |
|
|
|
70 |
|
|
/*
|
71 |
|
|
* console_sem protects the console_drivers list, and also
|
72 |
|
|
* provides serialisation for access to the entire console
|
73 |
|
|
* driver system.
|
74 |
|
|
*/
|
75 |
|
|
static DECLARE_MUTEX(console_sem);
|
76 |
|
|
struct console *console_drivers;
|
77 |
|
|
|
78 |
|
|
/*
|
79 |
|
|
* logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
|
80 |
|
|
* It is also used in interesting ways to provide interlocking in
|
81 |
|
|
* release_console_sem().
|
82 |
|
|
*/
|
83 |
|
|
static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
|
84 |
|
|
|
85 |
|
|
static char log_buf[LOG_BUF_LEN];
|
86 |
|
|
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
|
87 |
|
|
|
88 |
|
|
/*
|
89 |
|
|
* The indices into log_buf are not constrained to LOG_BUF_LEN - they
|
90 |
|
|
* must be masked before subscripting
|
91 |
|
|
*/
|
92 |
|
|
static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
|
93 |
|
|
static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
|
94 |
|
|
static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
|
95 |
|
|
static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
|
96 |
|
|
|
97 |
|
|
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
|
98 |
|
|
static int preferred_console = -1;
|
99 |
|
|
|
100 |
|
|
/* Flag: console code may call schedule() */
|
101 |
|
|
static int console_may_schedule;
|
102 |
|
|
|
103 |
|
|
/*
|
104 |
|
|
* Setup a list of consoles. Called from init/main.c
|
105 |
|
|
*/
|
106 |
|
|
static int __init console_setup(char *str)
|
107 |
|
|
{
|
108 |
|
|
struct console_cmdline *c;
|
109 |
|
|
char name[sizeof(c->name)];
|
110 |
|
|
char *s, *options;
|
111 |
|
|
int i, idx;
|
112 |
|
|
|
113 |
|
|
/*
|
114 |
|
|
* Decode str into name, index, options.
|
115 |
|
|
*/
|
116 |
|
|
if (str[0] >= '0' && str[0] <= '9') {
|
117 |
|
|
strcpy(name, "ttyS");
|
118 |
|
|
strncpy(name + 4, str, sizeof(name) - 5);
|
119 |
|
|
} else
|
120 |
|
|
strncpy(name, str, sizeof(name) - 1);
|
121 |
|
|
name[sizeof(name) - 1] = 0;
|
122 |
|
|
if ((options = strchr(str, ',')) != NULL)
|
123 |
|
|
*(options++) = 0;
|
124 |
|
|
#ifdef __sparc__
|
125 |
|
|
if (!strcmp(str, "ttya"))
|
126 |
|
|
strcpy(name, "ttyS0");
|
127 |
|
|
if (!strcmp(str, "ttyb"))
|
128 |
|
|
strcpy(name, "ttyS1");
|
129 |
|
|
#endif
|
130 |
|
|
for(s = name; *s; s++)
|
131 |
|
|
if (*s >= '0' && *s <= '9')
|
132 |
|
|
break;
|
133 |
|
|
idx = simple_strtoul(s, NULL, 10);
|
134 |
|
|
*s = 0;
|
135 |
|
|
|
136 |
|
|
/*
|
137 |
|
|
* See if this tty is not yet registered, and
|
138 |
|
|
* if we have a slot free.
|
139 |
|
|
*/
|
140 |
|
|
for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
|
141 |
|
|
if (strcmp(console_cmdline[i].name, name) == 0 &&
|
142 |
|
|
console_cmdline[i].index == idx) {
|
143 |
|
|
preferred_console = i;
|
144 |
|
|
return 1;
|
145 |
|
|
}
|
146 |
|
|
if (i == MAX_CMDLINECONSOLES)
|
147 |
|
|
return 1;
|
148 |
|
|
preferred_console = i;
|
149 |
|
|
c = &console_cmdline[i];
|
150 |
|
|
memcpy(c->name, name, sizeof(c->name));
|
151 |
|
|
c->options = options;
|
152 |
|
|
c->index = idx;
|
153 |
|
|
return 1;
|
154 |
|
|
}
|
155 |
|
|
|
156 |
|
|
__setup("console=", console_setup);
|
157 |
|
|
|
158 |
|
|
/*
|
159 |
|
|
* Commands to do_syslog:
|
160 |
|
|
*
|
161 |
|
|
* 0 -- Close the log. Currently a NOP.
|
162 |
|
|
* 1 -- Open the log. Currently a NOP.
|
163 |
|
|
* 2 -- Read from the log.
|
164 |
|
|
* 3 -- Read all messages remaining in the ring buffer.
|
165 |
|
|
* 4 -- Read and clear all messages remaining in the ring buffer
|
166 |
|
|
* 5 -- Clear ring buffer.
|
167 |
|
|
* 6 -- Disable printk's to console
|
168 |
|
|
* 7 -- Enable printk's to console
|
169 |
|
|
* 8 -- Set level of messages printed to console
|
170 |
|
|
* 9 -- Return number of unread characters in the log buffer
|
171 |
|
|
*/
|
172 |
|
|
int do_syslog(int type, char * buf, int len)
|
173 |
|
|
{
|
174 |
|
|
unsigned long i, j, limit, count;
|
175 |
|
|
int do_clear = 0;
|
176 |
|
|
char c;
|
177 |
|
|
int error = 0;
|
178 |
|
|
|
179 |
|
|
switch (type) {
|
180 |
|
|
case 0: /* Close log */
|
181 |
|
|
break;
|
182 |
|
|
case 1: /* Open log */
|
183 |
|
|
break;
|
184 |
|
|
case 2: /* Read from log */
|
185 |
|
|
error = -EINVAL;
|
186 |
|
|
if (!buf || len < 0)
|
187 |
|
|
goto out;
|
188 |
|
|
error = 0;
|
189 |
|
|
if (!len)
|
190 |
|
|
goto out;
|
191 |
|
|
error = verify_area(VERIFY_WRITE,buf,len);
|
192 |
|
|
if (error)
|
193 |
|
|
goto out;
|
194 |
|
|
error = wait_event_interruptible(log_wait, (log_start - log_end));
|
195 |
|
|
if (error)
|
196 |
|
|
goto out;
|
197 |
|
|
i = 0;
|
198 |
|
|
spin_lock_irq(&logbuf_lock);
|
199 |
|
|
while ((log_start != log_end) && i < len) {
|
200 |
|
|
c = LOG_BUF(log_start);
|
201 |
|
|
log_start++;
|
202 |
|
|
spin_unlock_irq(&logbuf_lock);
|
203 |
|
|
__put_user(c,buf);
|
204 |
|
|
buf++;
|
205 |
|
|
i++;
|
206 |
|
|
spin_lock_irq(&logbuf_lock);
|
207 |
|
|
}
|
208 |
|
|
spin_unlock_irq(&logbuf_lock);
|
209 |
|
|
error = i;
|
210 |
|
|
break;
|
211 |
|
|
case 4: /* Read/clear last kernel messages */
|
212 |
|
|
do_clear = 1;
|
213 |
|
|
/* FALL THRU */
|
214 |
|
|
case 3: /* Read last kernel messages */
|
215 |
|
|
error = -EINVAL;
|
216 |
|
|
if (!buf || len < 0)
|
217 |
|
|
goto out;
|
218 |
|
|
error = 0;
|
219 |
|
|
if (!len)
|
220 |
|
|
goto out;
|
221 |
|
|
error = verify_area(VERIFY_WRITE,buf,len);
|
222 |
|
|
if (error)
|
223 |
|
|
goto out;
|
224 |
|
|
count = len;
|
225 |
|
|
if (count > LOG_BUF_LEN)
|
226 |
|
|
count = LOG_BUF_LEN;
|
227 |
|
|
spin_lock_irq(&logbuf_lock);
|
228 |
|
|
if (count > logged_chars)
|
229 |
|
|
count = logged_chars;
|
230 |
|
|
if (do_clear)
|
231 |
|
|
logged_chars = 0;
|
232 |
|
|
limit = log_end;
|
233 |
|
|
/*
|
234 |
|
|
* __put_user() could sleep, and while we sleep
|
235 |
|
|
* printk() could overwrite the messages
|
236 |
|
|
* we try to copy to user space. Therefore
|
237 |
|
|
* the messages are copied in reverse. <manfreds>
|
238 |
|
|
*/
|
239 |
|
|
for(i=0;i < count;i++) {
|
240 |
|
|
j = limit-1-i;
|
241 |
|
|
if (j+LOG_BUF_LEN < log_end)
|
242 |
|
|
break;
|
243 |
|
|
c = LOG_BUF(j);
|
244 |
|
|
spin_unlock_irq(&logbuf_lock);
|
245 |
|
|
__put_user(c,&buf[count-1-i]);
|
246 |
|
|
spin_lock_irq(&logbuf_lock);
|
247 |
|
|
}
|
248 |
|
|
spin_unlock_irq(&logbuf_lock);
|
249 |
|
|
error = i;
|
250 |
|
|
if(i != count) {
|
251 |
|
|
int offset = count-error;
|
252 |
|
|
/* buffer overflow during copy, correct user buffer. */
|
253 |
|
|
for(i=0;i<error;i++) {
|
254 |
|
|
__get_user(c,&buf[i+offset]);
|
255 |
|
|
__put_user(c,&buf[i]);
|
256 |
|
|
}
|
257 |
|
|
}
|
258 |
|
|
|
259 |
|
|
break;
|
260 |
|
|
case 5: /* Clear ring buffer */
|
261 |
|
|
spin_lock_irq(&logbuf_lock);
|
262 |
|
|
logged_chars = 0;
|
263 |
|
|
spin_unlock_irq(&logbuf_lock);
|
264 |
|
|
break;
|
265 |
|
|
case 6: /* Disable logging to console */
|
266 |
|
|
spin_lock_irq(&logbuf_lock);
|
267 |
|
|
console_loglevel = minimum_console_loglevel;
|
268 |
|
|
spin_unlock_irq(&logbuf_lock);
|
269 |
|
|
break;
|
270 |
|
|
case 7: /* Enable logging to console */
|
271 |
|
|
spin_lock_irq(&logbuf_lock);
|
272 |
|
|
console_loglevel = default_console_loglevel;
|
273 |
|
|
spin_unlock_irq(&logbuf_lock);
|
274 |
|
|
break;
|
275 |
|
|
case 8: /* Set level of messages printed to console */
|
276 |
|
|
error = -EINVAL;
|
277 |
|
|
if (len < 1 || len > 8)
|
278 |
|
|
goto out;
|
279 |
|
|
if (len < minimum_console_loglevel)
|
280 |
|
|
len = minimum_console_loglevel;
|
281 |
|
|
spin_lock_irq(&logbuf_lock);
|
282 |
|
|
console_loglevel = len;
|
283 |
|
|
spin_unlock_irq(&logbuf_lock);
|
284 |
|
|
error = 0;
|
285 |
|
|
break;
|
286 |
|
|
case 9: /* Number of chars in the log buffer */
|
287 |
|
|
spin_lock_irq(&logbuf_lock);
|
288 |
|
|
error = log_end - log_start;
|
289 |
|
|
spin_unlock_irq(&logbuf_lock);
|
290 |
|
|
break;
|
291 |
|
|
default:
|
292 |
|
|
error = -EINVAL;
|
293 |
|
|
break;
|
294 |
|
|
}
|
295 |
|
|
out:
|
296 |
|
|
return error;
|
297 |
|
|
}
|
298 |
|
|
|
299 |
|
|
asmlinkage long sys_syslog(int type, char * buf, int len)
|
300 |
|
|
{
|
301 |
|
|
if ((type != 3) && !capable(CAP_SYS_ADMIN))
|
302 |
|
|
return -EPERM;
|
303 |
|
|
return do_syslog(type, buf, len);
|
304 |
|
|
}
|
305 |
|
|
|
306 |
|
|
/*
|
307 |
|
|
* Call the console drivers on a range of log_buf
|
308 |
|
|
*/
|
309 |
|
|
static void __call_console_drivers(unsigned long start, unsigned long end)
|
310 |
|
|
{
|
311 |
|
|
struct console *con;
|
312 |
|
|
|
313 |
|
|
for (con = console_drivers; con; con = con->next) {
|
314 |
|
|
if ((con->flags & CON_ENABLED) && con->write)
|
315 |
|
|
con->write(con, &LOG_BUF(start), end - start);
|
316 |
|
|
}
|
317 |
|
|
}
|
318 |
|
|
|
319 |
|
|
/*
|
320 |
|
|
* Write out chars from start to end - 1 inclusive
|
321 |
|
|
*/
|
322 |
|
|
static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
|
323 |
|
|
{
|
324 |
|
|
if (msg_log_level < console_loglevel && console_drivers && start != end) {
|
325 |
|
|
if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
|
326 |
|
|
/* wrapped write */
|
327 |
|
|
__call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
|
328 |
|
|
__call_console_drivers(0, end & LOG_BUF_MASK);
|
329 |
|
|
} else {
|
330 |
|
|
__call_console_drivers(start, end);
|
331 |
|
|
}
|
332 |
|
|
}
|
333 |
|
|
}
|
334 |
|
|
|
335 |
|
|
/*
|
336 |
|
|
* Call the console drivers, asking them to write out
|
337 |
|
|
* log_buf[start] to log_buf[end - 1].
|
338 |
|
|
* The console_sem must be held.
|
339 |
|
|
*/
|
340 |
|
|
static void call_console_drivers(unsigned long start, unsigned long end)
|
341 |
|
|
{
|
342 |
|
|
unsigned long cur_index, start_print;
|
343 |
|
|
static int msg_level = -1;
|
344 |
|
|
|
345 |
|
|
if (((long)(start - end)) > 0)
|
346 |
|
|
BUG();
|
347 |
|
|
|
348 |
|
|
cur_index = start;
|
349 |
|
|
start_print = start;
|
350 |
|
|
while (cur_index != end) {
|
351 |
|
|
if ( msg_level < 0 &&
|
352 |
|
|
((end - cur_index) > 2) &&
|
353 |
|
|
LOG_BUF(cur_index + 0) == '<' &&
|
354 |
|
|
LOG_BUF(cur_index + 1) >= '0' &&
|
355 |
|
|
LOG_BUF(cur_index + 1) <= '7' &&
|
356 |
|
|
LOG_BUF(cur_index + 2) == '>')
|
357 |
|
|
{
|
358 |
|
|
msg_level = LOG_BUF(cur_index + 1) - '0';
|
359 |
|
|
cur_index += 3;
|
360 |
|
|
start_print = cur_index;
|
361 |
|
|
}
|
362 |
|
|
while (cur_index != end) {
|
363 |
|
|
char c = LOG_BUF(cur_index);
|
364 |
|
|
cur_index++;
|
365 |
|
|
|
366 |
|
|
if (c == '\n') {
|
367 |
|
|
if (msg_level < 0) {
|
368 |
|
|
/*
|
369 |
|
|
* printk() has already given us loglevel tags in
|
370 |
|
|
* the buffer. This code is here in case the
|
371 |
|
|
* log buffer has wrapped right round and scribbled
|
372 |
|
|
* on those tags
|
373 |
|
|
*/
|
374 |
|
|
msg_level = default_message_loglevel;
|
375 |
|
|
}
|
376 |
|
|
_call_console_drivers(start_print, cur_index, msg_level);
|
377 |
|
|
msg_level = -1;
|
378 |
|
|
start_print = cur_index;
|
379 |
|
|
break;
|
380 |
|
|
}
|
381 |
|
|
}
|
382 |
|
|
}
|
383 |
|
|
_call_console_drivers(start_print, end, msg_level);
|
384 |
|
|
}
|
385 |
|
|
|
386 |
|
|
static void emit_log_char(char c)
|
387 |
|
|
{
|
388 |
|
|
LOG_BUF(log_end) = c;
|
389 |
|
|
log_end++;
|
390 |
|
|
if (log_end - log_start > LOG_BUF_LEN)
|
391 |
|
|
log_start = log_end - LOG_BUF_LEN;
|
392 |
|
|
if (log_end - con_start > LOG_BUF_LEN)
|
393 |
|
|
con_start = log_end - LOG_BUF_LEN;
|
394 |
|
|
if (logged_chars < LOG_BUF_LEN)
|
395 |
|
|
logged_chars++;
|
396 |
|
|
}
|
397 |
|
|
|
398 |
|
|
/*
|
399 |
|
|
* This is printk. It can be called from any context. We want it to work.
|
400 |
|
|
*
|
401 |
|
|
* We try to grab the console_sem. If we succeed, it's easy - we log the output and
|
402 |
|
|
* call the console drivers. If we fail to get the semaphore we place the output
|
403 |
|
|
* into the log buffer and return. The current holder of the console_sem will
|
404 |
|
|
* notice the new output in release_console_sem() and will send it to the
|
405 |
|
|
* consoles before releasing the semaphore.
|
406 |
|
|
*
|
407 |
|
|
* One effect of this deferred printing is that code which calls printk() and
|
408 |
|
|
* then changes console_loglevel may break. This is because console_loglevel
|
409 |
|
|
* is inspected when the actual printing occurs.
|
410 |
|
|
*/
|
411 |
|
|
asmlinkage int printk(const char *fmt, ...)
|
412 |
|
|
{
|
413 |
|
|
va_list args;
|
414 |
|
|
unsigned long flags;
|
415 |
|
|
int printed_len;
|
416 |
|
|
char *p;
|
417 |
|
|
static char printk_buf[1024];
|
418 |
|
|
static int log_level_unknown = 1;
|
419 |
|
|
|
420 |
|
|
if (oops_in_progress) {
|
421 |
|
|
/* If a crash is occurring, make sure we can't deadlock */
|
422 |
|
|
spin_lock_init(&logbuf_lock);
|
423 |
|
|
/* And make sure that we print immediately */
|
424 |
|
|
init_MUTEX(&console_sem);
|
425 |
|
|
}
|
426 |
|
|
|
427 |
|
|
/* This stops the holder of console_sem just where we want him */
|
428 |
|
|
spin_lock_irqsave(&logbuf_lock, flags);
|
429 |
|
|
|
430 |
|
|
/* Emit the output into the temporary buffer */
|
431 |
|
|
va_start(args, fmt);
|
432 |
|
|
printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
|
433 |
|
|
va_end(args);
|
434 |
|
|
|
435 |
|
|
/*
|
436 |
|
|
* Copy the output into log_buf. If the caller didn't provide
|
437 |
|
|
* appropriate log level tags, we insert them here
|
438 |
|
|
*/
|
439 |
|
|
for (p = printk_buf; *p; p++) {
|
440 |
|
|
if (log_level_unknown) {
|
441 |
|
|
if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
|
442 |
|
|
emit_log_char('<');
|
443 |
|
|
emit_log_char(default_message_loglevel + '0');
|
444 |
|
|
emit_log_char('>');
|
445 |
|
|
}
|
446 |
|
|
log_level_unknown = 0;
|
447 |
|
|
}
|
448 |
|
|
emit_log_char(*p);
|
449 |
|
|
if (*p == '\n')
|
450 |
|
|
log_level_unknown = 1;
|
451 |
|
|
}
|
452 |
|
|
|
453 |
|
|
if (!arch_consoles_callable()) {
|
454 |
|
|
/*
|
455 |
|
|
* On some architectures, the consoles are not usable
|
456 |
|
|
* on secondary CPUs early in the boot process.
|
457 |
|
|
*/
|
458 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
459 |
|
|
goto out;
|
460 |
|
|
}
|
461 |
|
|
if (!down_trylock(&console_sem)) {
|
462 |
|
|
/*
|
463 |
|
|
* We own the drivers. We can drop the spinlock and let
|
464 |
|
|
* release_console_sem() print the text
|
465 |
|
|
*/
|
466 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
467 |
|
|
console_may_schedule = 0;
|
468 |
|
|
release_console_sem();
|
469 |
|
|
} else {
|
470 |
|
|
/*
|
471 |
|
|
* Someone else owns the drivers. We drop the spinlock, which
|
472 |
|
|
* allows the semaphore holder to proceed and to call the
|
473 |
|
|
* console drivers with the output which we just produced.
|
474 |
|
|
*/
|
475 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
476 |
|
|
}
|
477 |
|
|
out:
|
478 |
|
|
return printed_len;
|
479 |
|
|
}
|
480 |
|
|
EXPORT_SYMBOL(printk);
|
481 |
|
|
|
482 |
|
|
/**
|
483 |
|
|
* acquire_console_sem - lock the console system for exclusive use.
|
484 |
|
|
*
|
485 |
|
|
* Acquires a semaphore which guarantees that the caller has
|
486 |
|
|
* exclusive access to the console system and the console_drivers list.
|
487 |
|
|
*
|
488 |
|
|
* Can sleep, returns nothing.
|
489 |
|
|
*/
|
490 |
|
|
void acquire_console_sem(void)
|
491 |
|
|
{
|
492 |
|
|
if (in_interrupt())
|
493 |
|
|
BUG();
|
494 |
|
|
down(&console_sem);
|
495 |
|
|
console_may_schedule = 1;
|
496 |
|
|
}
|
497 |
|
|
EXPORT_SYMBOL(acquire_console_sem);
|
498 |
|
|
|
499 |
|
|
/**
|
500 |
|
|
* release_console_sem - unlock the console system
|
501 |
|
|
*
|
502 |
|
|
* Releases the semaphore which the caller holds on the console system
|
503 |
|
|
* and the console driver list.
|
504 |
|
|
*
|
505 |
|
|
* While the semaphore was held, console output may have been buffered
|
506 |
|
|
* by printk(). If this is the case, release_console_sem() emits
|
507 |
|
|
* the output prior to releasing the semaphore.
|
508 |
|
|
*
|
509 |
|
|
* If there is output waiting for klogd, we wake it up.
|
510 |
|
|
*
|
511 |
|
|
* release_console_sem() may be called from any context.
|
512 |
|
|
*/
|
513 |
|
|
void release_console_sem(void)
|
514 |
|
|
{
|
515 |
|
|
unsigned long flags;
|
516 |
|
|
unsigned long _con_start, _log_end;
|
517 |
|
|
unsigned long must_wake_klogd = 0;
|
518 |
|
|
|
519 |
|
|
for ( ; ; ) {
|
520 |
|
|
spin_lock_irqsave(&logbuf_lock, flags);
|
521 |
|
|
must_wake_klogd |= log_start - log_end;
|
522 |
|
|
if (con_start == log_end)
|
523 |
|
|
break; /* Nothing to print */
|
524 |
|
|
_con_start = con_start;
|
525 |
|
|
_log_end = log_end;
|
526 |
|
|
con_start = log_end; /* Flush */
|
527 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
528 |
|
|
call_console_drivers(_con_start, _log_end);
|
529 |
|
|
}
|
530 |
|
|
console_may_schedule = 0;
|
531 |
|
|
up(&console_sem);
|
532 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
533 |
|
|
if (must_wake_klogd && !oops_in_progress)
|
534 |
|
|
wake_up_interruptible(&log_wait);
|
535 |
|
|
}
|
536 |
|
|
|
537 |
|
|
/** console_conditional_schedule - yield the CPU if required
|
538 |
|
|
*
|
539 |
|
|
* If the console code is currently allowed to sleep, and
|
540 |
|
|
* if this CPU should yield the CPU to another task, do
|
541 |
|
|
* so here.
|
542 |
|
|
*
|
543 |
|
|
* Must be called within acquire_console_sem().
|
544 |
|
|
*/
|
545 |
|
|
void console_conditional_schedule(void)
|
546 |
|
|
{
|
547 |
|
|
if (console_may_schedule && current->need_resched) {
|
548 |
|
|
set_current_state(TASK_RUNNING);
|
549 |
|
|
schedule();
|
550 |
|
|
}
|
551 |
|
|
}
|
552 |
|
|
|
553 |
|
|
void console_print(const char *s)
|
554 |
|
|
{
|
555 |
|
|
printk(KERN_EMERG "%s", s);
|
556 |
|
|
}
|
557 |
|
|
EXPORT_SYMBOL(console_print);
|
558 |
|
|
|
559 |
|
|
void console_unblank(void)
|
560 |
|
|
{
|
561 |
|
|
struct console *c;
|
562 |
|
|
|
563 |
|
|
/*
|
564 |
|
|
* Try to get the console semaphore. If someone else owns it
|
565 |
|
|
* we have to return without unblanking because console_unblank
|
566 |
|
|
* may be called in interrupt context.
|
567 |
|
|
*/
|
568 |
|
|
if (down_trylock(&console_sem) != 0)
|
569 |
|
|
return;
|
570 |
|
|
console_may_schedule = 0;
|
571 |
|
|
for (c = console_drivers; c != NULL; c = c->next)
|
572 |
|
|
if ((c->flags & CON_ENABLED) && c->unblank)
|
573 |
|
|
c->unblank();
|
574 |
|
|
release_console_sem();
|
575 |
|
|
}
|
576 |
|
|
EXPORT_SYMBOL(console_unblank);
|
577 |
|
|
|
578 |
|
|
/*
|
579 |
|
|
* The console driver calls this routine during kernel initialization
|
580 |
|
|
* to register the console printing procedure with printk() and to
|
581 |
|
|
* print any messages that were printed by the kernel before the
|
582 |
|
|
* console driver was initialized.
|
583 |
|
|
*/
|
584 |
|
|
void register_console(struct console * console)
|
585 |
|
|
{
|
586 |
|
|
int i;
|
587 |
|
|
unsigned long flags;
|
588 |
|
|
|
589 |
|
|
/*
|
590 |
|
|
* See if we want to use this console driver. If we
|
591 |
|
|
* didn't select a console we take the first one
|
592 |
|
|
* that registers here.
|
593 |
|
|
*/
|
594 |
|
|
if (preferred_console < 0) {
|
595 |
|
|
if (console->index < 0)
|
596 |
|
|
console->index = 0;
|
597 |
|
|
if (console->setup == NULL ||
|
598 |
|
|
console->setup(console, NULL) == 0) {
|
599 |
|
|
console->flags |= CON_ENABLED | CON_CONSDEV;
|
600 |
|
|
preferred_console = 0;
|
601 |
|
|
}
|
602 |
|
|
}
|
603 |
|
|
|
604 |
|
|
/*
|
605 |
|
|
* See if this console matches one we selected on
|
606 |
|
|
* the command line.
|
607 |
|
|
*/
|
608 |
|
|
for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
|
609 |
|
|
if (strcmp(console_cmdline[i].name, console->name) != 0)
|
610 |
|
|
continue;
|
611 |
|
|
if (console->index >= 0 &&
|
612 |
|
|
console->index != console_cmdline[i].index)
|
613 |
|
|
continue;
|
614 |
|
|
if (console->index < 0)
|
615 |
|
|
console->index = console_cmdline[i].index;
|
616 |
|
|
if (console->setup &&
|
617 |
|
|
console->setup(console, console_cmdline[i].options) != 0)
|
618 |
|
|
break;
|
619 |
|
|
console->flags |= CON_ENABLED;
|
620 |
|
|
console->index = console_cmdline[i].index;
|
621 |
|
|
if (i == preferred_console)
|
622 |
|
|
console->flags |= CON_CONSDEV;
|
623 |
|
|
break;
|
624 |
|
|
}
|
625 |
|
|
|
626 |
|
|
if (!(console->flags & CON_ENABLED))
|
627 |
|
|
return;
|
628 |
|
|
|
629 |
|
|
/*
|
630 |
|
|
* Put this console in the list - keep the
|
631 |
|
|
* preferred driver at the head of the list.
|
632 |
|
|
*/
|
633 |
|
|
acquire_console_sem();
|
634 |
|
|
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
|
635 |
|
|
console->next = console_drivers;
|
636 |
|
|
console_drivers = console;
|
637 |
|
|
} else {
|
638 |
|
|
console->next = console_drivers->next;
|
639 |
|
|
console_drivers->next = console;
|
640 |
|
|
}
|
641 |
|
|
if (console->flags & CON_PRINTBUFFER) {
|
642 |
|
|
/*
|
643 |
|
|
* release_console_sem() will print out the buffered messages for us.
|
644 |
|
|
*/
|
645 |
|
|
spin_lock_irqsave(&logbuf_lock, flags);
|
646 |
|
|
con_start = log_start;
|
647 |
|
|
spin_unlock_irqrestore(&logbuf_lock, flags);
|
648 |
|
|
}
|
649 |
|
|
release_console_sem();
|
650 |
|
|
}
|
651 |
|
|
EXPORT_SYMBOL(register_console);
|
652 |
|
|
|
653 |
|
|
int unregister_console(struct console * console)
|
654 |
|
|
{
|
655 |
|
|
struct console *a,*b;
|
656 |
|
|
int res = 1;
|
657 |
|
|
|
658 |
|
|
acquire_console_sem();
|
659 |
|
|
if (console_drivers == console) {
|
660 |
|
|
console_drivers=console->next;
|
661 |
|
|
res = 0;
|
662 |
|
|
} else {
|
663 |
|
|
for (a=console_drivers->next, b=console_drivers ;
|
664 |
|
|
a; b=a, a=b->next) {
|
665 |
|
|
if (a == console) {
|
666 |
|
|
b->next = a->next;
|
667 |
|
|
res = 0;
|
668 |
|
|
break;
|
669 |
|
|
}
|
670 |
|
|
}
|
671 |
|
|
}
|
672 |
|
|
|
673 |
|
|
/* If last console is removed, we re-enable picking the first
|
674 |
|
|
* one that gets registered. Without that, pmac early boot console
|
675 |
|
|
* would prevent fbcon from taking over.
|
676 |
|
|
*/
|
677 |
|
|
if (console_drivers == NULL)
|
678 |
|
|
preferred_console = -1;
|
679 |
|
|
|
680 |
|
|
|
681 |
|
|
release_console_sem();
|
682 |
|
|
return res;
|
683 |
|
|
}
|
684 |
|
|
EXPORT_SYMBOL(unregister_console);
|
685 |
|
|
|
686 |
|
|
/**
|
687 |
|
|
* tty_write_message - write a message to a certain tty, not just the console.
|
688 |
|
|
*
|
689 |
|
|
* This is used for messages that need to be redirected to a specific tty.
|
690 |
|
|
* We don't put it into the syslog queue right now maybe in the future if
|
691 |
|
|
* really needed.
|
692 |
|
|
*/
|
693 |
|
|
void tty_write_message(struct tty_struct *tty, char *msg)
|
694 |
|
|
{
|
695 |
|
|
if (tty && tty->driver.write)
|
696 |
|
|
tty->driver.write(tty, 0, msg, strlen(msg));
|
697 |
|
|
return;
|
698 |
|
|
}
|