.. | .. |
---|
8 | 8 | * |
---|
9 | 9 | * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc. |
---|
10 | 10 | */ |
---|
| 11 | + |
---|
| 12 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
| 13 | + |
---|
11 | 14 | #include <linux/kernel.h> |
---|
12 | 15 | #include <linux/ctype.h> |
---|
13 | 16 | #include <linux/kgdb.h> |
---|
.. | .. |
---|
17 | 20 | #include <linux/vt_kern.h> |
---|
18 | 21 | #include <linux/input.h> |
---|
19 | 22 | #include <linux/module.h> |
---|
| 23 | +#include <linux/platform_device.h> |
---|
| 24 | +#include <linux/serial_core.h> |
---|
20 | 25 | |
---|
21 | 26 | #define MAX_CONFIG_LEN 40 |
---|
22 | 27 | |
---|
.. | .. |
---|
24 | 29 | |
---|
25 | 30 | /* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ |
---|
26 | 31 | static int configured = -1; |
---|
| 32 | +static DEFINE_MUTEX(config_mutex); |
---|
27 | 33 | |
---|
28 | 34 | static char config[MAX_CONFIG_LEN]; |
---|
29 | 35 | static struct kparam_string kps = { |
---|
.. | .. |
---|
34 | 40 | static int kgdboc_use_kms; /* 1 if we use kernel mode switching */ |
---|
35 | 41 | static struct tty_driver *kgdb_tty_driver; |
---|
36 | 42 | static int kgdb_tty_line; |
---|
| 43 | + |
---|
| 44 | +static struct platform_device *kgdboc_pdev; |
---|
| 45 | + |
---|
| 46 | +#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) |
---|
| 47 | +static struct kgdb_io kgdboc_earlycon_io_ops; |
---|
| 48 | +static int (*earlycon_orig_exit)(struct console *con); |
---|
| 49 | +#endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ |
---|
37 | 50 | |
---|
38 | 51 | #ifdef CONFIG_KDB_KEYBOARD |
---|
39 | 52 | static int kgdboc_reset_connect(struct input_handler *handler, |
---|
.. | .. |
---|
128 | 141 | #define kgdboc_restore_input() |
---|
129 | 142 | #endif /* ! CONFIG_KDB_KEYBOARD */ |
---|
130 | 143 | |
---|
| 144 | +#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) |
---|
| 145 | +static void cleanup_earlycon(void) |
---|
| 146 | +{ |
---|
| 147 | + if (kgdboc_earlycon_io_ops.cons) |
---|
| 148 | + kgdb_unregister_io_module(&kgdboc_earlycon_io_ops); |
---|
| 149 | +} |
---|
| 150 | +#else /* !IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ |
---|
| 151 | +static inline void cleanup_earlycon(void) { } |
---|
| 152 | +#endif /* !IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ |
---|
| 153 | + |
---|
131 | 154 | static void cleanup_kgdboc(void) |
---|
132 | 155 | { |
---|
| 156 | + cleanup_earlycon(); |
---|
| 157 | + |
---|
| 158 | + if (configured != 1) |
---|
| 159 | + return; |
---|
| 160 | + |
---|
133 | 161 | if (kgdb_unregister_nmi_console()) |
---|
134 | 162 | return; |
---|
135 | 163 | kgdboc_unregister_kbd(); |
---|
136 | | - if (configured == 1) |
---|
137 | | - kgdb_unregister_io_module(&kgdboc_io_ops); |
---|
| 164 | + kgdb_unregister_io_module(&kgdboc_io_ops); |
---|
138 | 165 | } |
---|
139 | 166 | |
---|
140 | 167 | static int configure_kgdboc(void) |
---|
.. | .. |
---|
150 | 177 | goto noconfig; |
---|
151 | 178 | } |
---|
152 | 179 | |
---|
153 | | - kgdboc_io_ops.is_console = 0; |
---|
| 180 | + kgdboc_io_ops.cons = NULL; |
---|
154 | 181 | kgdb_tty_driver = NULL; |
---|
155 | 182 | |
---|
156 | 183 | kgdboc_use_kms = 0; |
---|
.. | .. |
---|
166 | 193 | if (!p) |
---|
167 | 194 | goto noconfig; |
---|
168 | 195 | |
---|
169 | | - cons = console_drivers; |
---|
170 | | - while (cons) { |
---|
| 196 | + for_each_console(cons) { |
---|
171 | 197 | int idx; |
---|
172 | 198 | if (cons->device && cons->device(cons, &idx) == p && |
---|
173 | 199 | idx == tty_line) { |
---|
174 | | - kgdboc_io_ops.is_console = 1; |
---|
| 200 | + kgdboc_io_ops.cons = cons; |
---|
175 | 201 | break; |
---|
176 | 202 | } |
---|
177 | | - cons = cons->next; |
---|
178 | 203 | } |
---|
179 | 204 | |
---|
180 | 205 | kgdb_tty_driver = p; |
---|
.. | .. |
---|
197 | 222 | kgdb_unregister_io_module(&kgdboc_io_ops); |
---|
198 | 223 | noconfig: |
---|
199 | 224 | kgdboc_unregister_kbd(); |
---|
200 | | - config[0] = 0; |
---|
201 | 225 | configured = 0; |
---|
202 | | - cleanup_kgdboc(); |
---|
203 | 226 | |
---|
204 | 227 | return err; |
---|
205 | 228 | } |
---|
206 | 229 | |
---|
| 230 | +static int kgdboc_probe(struct platform_device *pdev) |
---|
| 231 | +{ |
---|
| 232 | + int ret = 0; |
---|
| 233 | + |
---|
| 234 | + mutex_lock(&config_mutex); |
---|
| 235 | + if (configured != 1) { |
---|
| 236 | + ret = configure_kgdboc(); |
---|
| 237 | + |
---|
| 238 | + /* Convert "no device" to "defer" so we'll keep trying */ |
---|
| 239 | + if (ret == -ENODEV) |
---|
| 240 | + ret = -EPROBE_DEFER; |
---|
| 241 | + } |
---|
| 242 | + mutex_unlock(&config_mutex); |
---|
| 243 | + |
---|
| 244 | + return ret; |
---|
| 245 | +} |
---|
| 246 | + |
---|
| 247 | +static struct platform_driver kgdboc_platform_driver = { |
---|
| 248 | + .probe = kgdboc_probe, |
---|
| 249 | + .driver = { |
---|
| 250 | + .name = "kgdboc", |
---|
| 251 | + .suppress_bind_attrs = true, |
---|
| 252 | + }, |
---|
| 253 | +}; |
---|
| 254 | + |
---|
207 | 255 | static int __init init_kgdboc(void) |
---|
208 | 256 | { |
---|
209 | | - /* Already configured? */ |
---|
210 | | - if (configured == 1) |
---|
| 257 | + int ret; |
---|
| 258 | + |
---|
| 259 | + /* |
---|
| 260 | + * kgdboc is a little bit of an odd "platform_driver". It can be |
---|
| 261 | + * up and running long before the platform_driver object is |
---|
| 262 | + * created and thus doesn't actually store anything in it. There's |
---|
| 263 | + * only one instance of kgdb so anything is stored as global state. |
---|
| 264 | + * The platform_driver is only created so that we can leverage the |
---|
| 265 | + * kernel's mechanisms (like -EPROBE_DEFER) to call us when our |
---|
| 266 | + * underlying tty is ready. Here we init our platform driver and |
---|
| 267 | + * then create the single kgdboc instance. |
---|
| 268 | + */ |
---|
| 269 | + ret = platform_driver_register(&kgdboc_platform_driver); |
---|
| 270 | + if (ret) |
---|
| 271 | + return ret; |
---|
| 272 | + |
---|
| 273 | + kgdboc_pdev = platform_device_alloc("kgdboc", PLATFORM_DEVID_NONE); |
---|
| 274 | + if (!kgdboc_pdev) { |
---|
| 275 | + ret = -ENOMEM; |
---|
| 276 | + goto err_did_register; |
---|
| 277 | + } |
---|
| 278 | + |
---|
| 279 | + ret = platform_device_add(kgdboc_pdev); |
---|
| 280 | + if (!ret) |
---|
211 | 281 | return 0; |
---|
212 | 282 | |
---|
213 | | - return configure_kgdboc(); |
---|
| 283 | + platform_device_put(kgdboc_pdev); |
---|
| 284 | + |
---|
| 285 | +err_did_register: |
---|
| 286 | + platform_driver_unregister(&kgdboc_platform_driver); |
---|
| 287 | + return ret; |
---|
| 288 | +} |
---|
| 289 | + |
---|
| 290 | +static void exit_kgdboc(void) |
---|
| 291 | +{ |
---|
| 292 | + mutex_lock(&config_mutex); |
---|
| 293 | + cleanup_kgdboc(); |
---|
| 294 | + mutex_unlock(&config_mutex); |
---|
| 295 | + |
---|
| 296 | + platform_device_unregister(kgdboc_pdev); |
---|
| 297 | + platform_driver_unregister(&kgdboc_platform_driver); |
---|
214 | 298 | } |
---|
215 | 299 | |
---|
216 | 300 | static int kgdboc_get_char(void) |
---|
.. | .. |
---|
233 | 317 | const struct kernel_param *kp) |
---|
234 | 318 | { |
---|
235 | 319 | size_t len = strlen(kmessage); |
---|
| 320 | + int ret = 0; |
---|
236 | 321 | |
---|
237 | 322 | if (len >= MAX_CONFIG_LEN) { |
---|
238 | | - printk(KERN_ERR "kgdboc: config string too long\n"); |
---|
| 323 | + pr_err("config string too long\n"); |
---|
239 | 324 | return -ENOSPC; |
---|
240 | 325 | } |
---|
241 | 326 | |
---|
242 | | - /* Only copy in the string if the init function has not run yet */ |
---|
243 | | - if (configured < 0) { |
---|
244 | | - strcpy(config, kmessage); |
---|
245 | | - return 0; |
---|
246 | | - } |
---|
247 | | - |
---|
248 | 327 | if (kgdb_connected) { |
---|
249 | | - printk(KERN_ERR |
---|
250 | | - "kgdboc: Cannot reconfigure while KGDB is connected.\n"); |
---|
251 | | - |
---|
| 328 | + pr_err("Cannot reconfigure while KGDB is connected.\n"); |
---|
252 | 329 | return -EBUSY; |
---|
253 | 330 | } |
---|
| 331 | + |
---|
| 332 | + mutex_lock(&config_mutex); |
---|
254 | 333 | |
---|
255 | 334 | strcpy(config, kmessage); |
---|
256 | 335 | /* Chop out \n char as a result of echo */ |
---|
.. | .. |
---|
260 | 339 | if (configured == 1) |
---|
261 | 340 | cleanup_kgdboc(); |
---|
262 | 341 | |
---|
263 | | - /* Go and configure with the new params. */ |
---|
264 | | - return configure_kgdboc(); |
---|
| 342 | + /* |
---|
| 343 | + * Configure with the new params as long as init already ran. |
---|
| 344 | + * Note that we can get called before init if someone loads us |
---|
| 345 | + * with "modprobe kgdboc kgdboc=..." or if they happen to use the |
---|
| 346 | + * the odd syntax of "kgdboc.kgdboc=..." on the kernel command. |
---|
| 347 | + */ |
---|
| 348 | + if (configured >= 0) |
---|
| 349 | + ret = configure_kgdboc(); |
---|
| 350 | + |
---|
| 351 | + /* |
---|
| 352 | + * If we couldn't configure then clear out the config. Note that |
---|
| 353 | + * specifying an invalid config on the kernel command line vs. |
---|
| 354 | + * through sysfs have slightly different behaviors. If we fail |
---|
| 355 | + * to configure what was specified on the kernel command line |
---|
| 356 | + * we'll leave it in the 'config' and return -EPROBE_DEFER from |
---|
| 357 | + * our probe. When specified through sysfs userspace is |
---|
| 358 | + * responsible for loading the tty driver before setting up. |
---|
| 359 | + */ |
---|
| 360 | + if (ret) |
---|
| 361 | + config[0] = '\0'; |
---|
| 362 | + |
---|
| 363 | + mutex_unlock(&config_mutex); |
---|
| 364 | + |
---|
| 365 | + return ret; |
---|
265 | 366 | } |
---|
266 | 367 | |
---|
267 | 368 | static int dbg_restore_graphics; |
---|
.. | .. |
---|
297 | 398 | .post_exception = kgdboc_post_exp_handler, |
---|
298 | 399 | }; |
---|
299 | 400 | |
---|
300 | | -#ifdef CONFIG_KGDB_SERIAL_CONSOLE |
---|
| 401 | +#if IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) |
---|
301 | 402 | static int kgdboc_option_setup(char *opt) |
---|
302 | 403 | { |
---|
303 | 404 | if (!opt) { |
---|
304 | 405 | pr_err("config string not provided\n"); |
---|
305 | | - return -EINVAL; |
---|
| 406 | + return 1; |
---|
306 | 407 | } |
---|
307 | 408 | |
---|
308 | 409 | if (strlen(opt) >= MAX_CONFIG_LEN) { |
---|
309 | 410 | pr_err("config string too long\n"); |
---|
310 | | - return -ENOSPC; |
---|
| 411 | + return 1; |
---|
311 | 412 | } |
---|
312 | 413 | strcpy(config, opt); |
---|
313 | 414 | |
---|
314 | | - return 0; |
---|
| 415 | + return 1; |
---|
315 | 416 | } |
---|
316 | 417 | |
---|
317 | 418 | __setup("kgdboc=", kgdboc_option_setup); |
---|
.. | .. |
---|
320 | 421 | /* This is only available if kgdboc is a built in for early debugging */ |
---|
321 | 422 | static int __init kgdboc_early_init(char *opt) |
---|
322 | 423 | { |
---|
323 | | - /* save the first character of the config string because the |
---|
324 | | - * init routine can destroy it. |
---|
325 | | - */ |
---|
326 | | - char save_ch; |
---|
327 | | - |
---|
328 | 424 | kgdboc_option_setup(opt); |
---|
329 | | - save_ch = config[0]; |
---|
330 | | - init_kgdboc(); |
---|
331 | | - config[0] = save_ch; |
---|
| 425 | + configure_kgdboc(); |
---|
332 | 426 | return 0; |
---|
333 | 427 | } |
---|
334 | 428 | |
---|
335 | 429 | early_param("ekgdboc", kgdboc_early_init); |
---|
336 | | -#endif /* CONFIG_KGDB_SERIAL_CONSOLE */ |
---|
| 430 | + |
---|
| 431 | +static int kgdboc_earlycon_get_char(void) |
---|
| 432 | +{ |
---|
| 433 | + char c; |
---|
| 434 | + |
---|
| 435 | + if (!kgdboc_earlycon_io_ops.cons->read(kgdboc_earlycon_io_ops.cons, |
---|
| 436 | + &c, 1)) |
---|
| 437 | + return NO_POLL_CHAR; |
---|
| 438 | + |
---|
| 439 | + return c; |
---|
| 440 | +} |
---|
| 441 | + |
---|
| 442 | +static void kgdboc_earlycon_put_char(u8 chr) |
---|
| 443 | +{ |
---|
| 444 | + kgdboc_earlycon_io_ops.cons->write(kgdboc_earlycon_io_ops.cons, &chr, |
---|
| 445 | + 1); |
---|
| 446 | +} |
---|
| 447 | + |
---|
| 448 | +static void kgdboc_earlycon_pre_exp_handler(void) |
---|
| 449 | +{ |
---|
| 450 | + struct console *con; |
---|
| 451 | + static bool already_warned; |
---|
| 452 | + |
---|
| 453 | + if (already_warned) |
---|
| 454 | + return; |
---|
| 455 | + |
---|
| 456 | + /* |
---|
| 457 | + * When the first normal console comes up the kernel will take all |
---|
| 458 | + * the boot consoles out of the list. Really, we should stop using |
---|
| 459 | + * the boot console when it does that but until a TTY is registered |
---|
| 460 | + * we have no other choice so we keep using it. Since not all |
---|
| 461 | + * serial drivers might be OK with this, print a warning once per |
---|
| 462 | + * boot if we detect this case. |
---|
| 463 | + */ |
---|
| 464 | + for_each_console(con) |
---|
| 465 | + if (con == kgdboc_earlycon_io_ops.cons) |
---|
| 466 | + return; |
---|
| 467 | + |
---|
| 468 | + already_warned = true; |
---|
| 469 | + pr_warn("kgdboc_earlycon is still using bootconsole\n"); |
---|
| 470 | +} |
---|
| 471 | + |
---|
| 472 | +static int kgdboc_earlycon_deferred_exit(struct console *con) |
---|
| 473 | +{ |
---|
| 474 | + /* |
---|
| 475 | + * If we get here it means the boot console is going away but we |
---|
| 476 | + * don't yet have a suitable replacement. Don't pass through to |
---|
| 477 | + * the original exit routine. We'll call it later in our deinit() |
---|
| 478 | + * function. For now, restore the original exit() function pointer |
---|
| 479 | + * as a sentinal that we've hit this point. |
---|
| 480 | + */ |
---|
| 481 | + con->exit = earlycon_orig_exit; |
---|
| 482 | + |
---|
| 483 | + return 0; |
---|
| 484 | +} |
---|
| 485 | + |
---|
| 486 | +static void kgdboc_earlycon_deinit(void) |
---|
| 487 | +{ |
---|
| 488 | + if (!kgdboc_earlycon_io_ops.cons) |
---|
| 489 | + return; |
---|
| 490 | + |
---|
| 491 | + if (kgdboc_earlycon_io_ops.cons->exit == kgdboc_earlycon_deferred_exit) |
---|
| 492 | + /* |
---|
| 493 | + * kgdboc_earlycon is exiting but original boot console exit |
---|
| 494 | + * was never called (AKA kgdboc_earlycon_deferred_exit() |
---|
| 495 | + * didn't ever run). Undo our trap. |
---|
| 496 | + */ |
---|
| 497 | + kgdboc_earlycon_io_ops.cons->exit = earlycon_orig_exit; |
---|
| 498 | + else if (kgdboc_earlycon_io_ops.cons->exit) |
---|
| 499 | + /* |
---|
| 500 | + * We skipped calling the exit() routine so we could try to |
---|
| 501 | + * keep using the boot console even after it went away. We're |
---|
| 502 | + * finally done so call the function now. |
---|
| 503 | + */ |
---|
| 504 | + kgdboc_earlycon_io_ops.cons->exit(kgdboc_earlycon_io_ops.cons); |
---|
| 505 | + |
---|
| 506 | + kgdboc_earlycon_io_ops.cons = NULL; |
---|
| 507 | +} |
---|
| 508 | + |
---|
| 509 | +static struct kgdb_io kgdboc_earlycon_io_ops = { |
---|
| 510 | + .name = "kgdboc_earlycon", |
---|
| 511 | + .read_char = kgdboc_earlycon_get_char, |
---|
| 512 | + .write_char = kgdboc_earlycon_put_char, |
---|
| 513 | + .pre_exception = kgdboc_earlycon_pre_exp_handler, |
---|
| 514 | + .deinit = kgdboc_earlycon_deinit, |
---|
| 515 | +}; |
---|
| 516 | + |
---|
| 517 | +#define MAX_CONSOLE_NAME_LEN (sizeof((struct console *) 0)->name) |
---|
| 518 | +static char kgdboc_earlycon_param[MAX_CONSOLE_NAME_LEN] __initdata; |
---|
| 519 | +static bool kgdboc_earlycon_late_enable __initdata; |
---|
| 520 | + |
---|
| 521 | +static int __init kgdboc_earlycon_init(char *opt) |
---|
| 522 | +{ |
---|
| 523 | + struct console *con; |
---|
| 524 | + |
---|
| 525 | + kdb_init(KDB_INIT_EARLY); |
---|
| 526 | + |
---|
| 527 | + /* |
---|
| 528 | + * Look for a matching console, or if the name was left blank just |
---|
| 529 | + * pick the first one we find. |
---|
| 530 | + */ |
---|
| 531 | + console_lock(); |
---|
| 532 | + for_each_console(con) { |
---|
| 533 | + if (con->write && con->read && |
---|
| 534 | + (con->flags & (CON_BOOT | CON_ENABLED)) && |
---|
| 535 | + (!opt || !opt[0] || strcmp(con->name, opt) == 0)) |
---|
| 536 | + break; |
---|
| 537 | + } |
---|
| 538 | + |
---|
| 539 | + if (!con) { |
---|
| 540 | + /* |
---|
| 541 | + * Both earlycon and kgdboc_earlycon are initialized during |
---|
| 542 | + * early parameter parsing. We cannot guarantee earlycon gets |
---|
| 543 | + * in first and, in any case, on ACPI systems earlycon may |
---|
| 544 | + * defer its own initialization (usually to somewhere within |
---|
| 545 | + * setup_arch() ). To cope with either of these situations |
---|
| 546 | + * we can defer our own initialization to a little later in |
---|
| 547 | + * the boot. |
---|
| 548 | + */ |
---|
| 549 | + if (!kgdboc_earlycon_late_enable) { |
---|
| 550 | + pr_info("No suitable earlycon yet, will try later\n"); |
---|
| 551 | + if (opt) |
---|
| 552 | + strscpy(kgdboc_earlycon_param, opt, |
---|
| 553 | + sizeof(kgdboc_earlycon_param)); |
---|
| 554 | + kgdboc_earlycon_late_enable = true; |
---|
| 555 | + } else { |
---|
| 556 | + pr_info("Couldn't find kgdb earlycon\n"); |
---|
| 557 | + } |
---|
| 558 | + goto unlock; |
---|
| 559 | + } |
---|
| 560 | + |
---|
| 561 | + kgdboc_earlycon_io_ops.cons = con; |
---|
| 562 | + pr_info("Going to register kgdb with earlycon '%s'\n", con->name); |
---|
| 563 | + if (kgdb_register_io_module(&kgdboc_earlycon_io_ops) != 0) { |
---|
| 564 | + kgdboc_earlycon_io_ops.cons = NULL; |
---|
| 565 | + pr_info("Failed to register kgdb with earlycon\n"); |
---|
| 566 | + } else { |
---|
| 567 | + /* Trap exit so we can keep earlycon longer if needed. */ |
---|
| 568 | + earlycon_orig_exit = con->exit; |
---|
| 569 | + con->exit = kgdboc_earlycon_deferred_exit; |
---|
| 570 | + } |
---|
| 571 | + |
---|
| 572 | +unlock: |
---|
| 573 | + console_unlock(); |
---|
| 574 | + |
---|
| 575 | + /* Non-zero means malformed option so we always return zero */ |
---|
| 576 | + return 0; |
---|
| 577 | +} |
---|
| 578 | + |
---|
| 579 | +early_param("kgdboc_earlycon", kgdboc_earlycon_init); |
---|
| 580 | + |
---|
| 581 | +/* |
---|
| 582 | + * This is only intended for the late adoption of an early console. |
---|
| 583 | + * |
---|
| 584 | + * It is not a reliable way to adopt regular consoles because we can not |
---|
| 585 | + * control what order console initcalls are made and, in any case, many |
---|
| 586 | + * regular consoles are registered much later in the boot process than |
---|
| 587 | + * the console initcalls! |
---|
| 588 | + */ |
---|
| 589 | +static int __init kgdboc_earlycon_late_init(void) |
---|
| 590 | +{ |
---|
| 591 | + if (kgdboc_earlycon_late_enable) |
---|
| 592 | + kgdboc_earlycon_init(kgdboc_earlycon_param); |
---|
| 593 | + return 0; |
---|
| 594 | +} |
---|
| 595 | +console_initcall(kgdboc_earlycon_late_init); |
---|
| 596 | + |
---|
| 597 | +#endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ |
---|
337 | 598 | |
---|
338 | 599 | module_init(init_kgdboc); |
---|
339 | | -module_exit(cleanup_kgdboc); |
---|
| 600 | +module_exit(exit_kgdboc); |
---|
340 | 601 | module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644); |
---|
341 | 602 | MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]"); |
---|
342 | 603 | MODULE_DESCRIPTION("KGDB Console TTY Driver"); |
---|