aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/kgdboc.c
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:24 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:24 -0400
commitada64e4c98eb5f04a9ca223c5ff9e7ac22ce6404 (patch)
tree48e284cf69157cf54302dcceb01ad7a07b889206 /drivers/serial/kgdboc.c
parenta0de055cf61338549b13079a5677ef2e1b6472ef (diff)
kgdboc,keyboard: Keyboard driver for kdb with kgdb
This patch adds in the kdb PS/2 keyboard driver. This was mostly a direct port from the original kdb where I cleaned up the code against checkpatch.pl and added the glue to stitch it into kgdb. This patch also enables early kdb debug via kgdbwait and the keyboard. All the access to configure kdb using either a serial console or the keyboard is done via kgdboc. If you want to use only the keyboard and want to break in early you would add to your kernel command arguments: kgdboc=kbd kgdbwait If you wanted serial and or the keyboard access you could use: kgdboc=kbd,ttyS0 You can also configure kgdboc as a kernel module or at run time with the sysfs where you can activate and deactivate kgdb. Turn it on: echo kbd,ttyS0 > /sys/module/kgdboc/parameters/kgdboc Turn it off: echo "" > /sys/module/kgdboc/parameters/kgdboc Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/serial/kgdboc.c')
-rw-r--r--drivers/serial/kgdboc.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index eadc1ab6bbce..ecef6e1a599a 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/ctype.h> 15#include <linux/ctype.h>
16#include <linux/kgdb.h> 16#include <linux/kgdb.h>
17#include <linux/kdb.h>
17#include <linux/tty.h> 18#include <linux/tty.h>
18 19
19#define MAX_CONFIG_LEN 40 20#define MAX_CONFIG_LEN 40
@@ -32,6 +33,40 @@ static struct kparam_string kps = {
32static struct tty_driver *kgdb_tty_driver; 33static struct tty_driver *kgdb_tty_driver;
33static int kgdb_tty_line; 34static int kgdb_tty_line;
34 35
36#ifdef CONFIG_KDB_KEYBOARD
37static int kgdboc_register_kbd(char **cptr)
38{
39 if (strncmp(*cptr, "kbd", 3) == 0) {
40 if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
41 kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
42 kdb_poll_idx++;
43 if (cptr[0][3] == ',')
44 *cptr += 4;
45 else
46 return 1;
47 }
48 }
49 return 0;
50}
51
52static void kgdboc_unregister_kbd(void)
53{
54 int i;
55
56 for (i = 0; i < kdb_poll_idx; i++) {
57 if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
58 kdb_poll_idx--;
59 kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
60 kdb_poll_funcs[kdb_poll_idx] = NULL;
61 i--;
62 }
63 }
64}
65#else /* ! CONFIG_KDB_KEYBOARD */
66#define kgdboc_register_kbd(x) 0
67#define kgdboc_unregister_kbd()
68#endif /* ! CONFIG_KDB_KEYBOARD */
69
35static int kgdboc_option_setup(char *opt) 70static int kgdboc_option_setup(char *opt)
36{ 71{
37 if (strlen(opt) > MAX_CONFIG_LEN) { 72 if (strlen(opt) > MAX_CONFIG_LEN) {
@@ -45,25 +80,38 @@ static int kgdboc_option_setup(char *opt)
45 80
46__setup("kgdboc=", kgdboc_option_setup); 81__setup("kgdboc=", kgdboc_option_setup);
47 82
83static void cleanup_kgdboc(void)
84{
85 kgdboc_unregister_kbd();
86 if (configured == 1)
87 kgdb_unregister_io_module(&kgdboc_io_ops);
88}
89
48static int configure_kgdboc(void) 90static int configure_kgdboc(void)
49{ 91{
50 struct tty_driver *p; 92 struct tty_driver *p;
51 int tty_line = 0; 93 int tty_line = 0;
52 int err; 94 int err;
95 char *cptr = config;
53 96
54 err = kgdboc_option_setup(config); 97 err = kgdboc_option_setup(config);
55 if (err || !strlen(config) || isspace(config[0])) 98 if (err || !strlen(config) || isspace(config[0]))
56 goto noconfig; 99 goto noconfig;
57 100
58 err = -ENODEV; 101 err = -ENODEV;
102 kgdb_tty_driver = NULL;
103
104 if (kgdboc_register_kbd(&cptr))
105 goto do_register;
59 106
60 p = tty_find_polling_driver(config, &tty_line); 107 p = tty_find_polling_driver(cptr, &tty_line);
61 if (!p) 108 if (!p)
62 goto noconfig; 109 goto noconfig;
63 110
64 kgdb_tty_driver = p; 111 kgdb_tty_driver = p;
65 kgdb_tty_line = tty_line; 112 kgdb_tty_line = tty_line;
66 113
114do_register:
67 err = kgdb_register_io_module(&kgdboc_io_ops); 115 err = kgdb_register_io_module(&kgdboc_io_ops);
68 if (err) 116 if (err)
69 goto noconfig; 117 goto noconfig;
@@ -75,6 +123,7 @@ static int configure_kgdboc(void)
75noconfig: 123noconfig:
76 config[0] = 0; 124 config[0] = 0;
77 configured = 0; 125 configured = 0;
126 cleanup_kgdboc();
78 127
79 return err; 128 return err;
80} 129}
@@ -88,20 +137,18 @@ static int __init init_kgdboc(void)
88 return configure_kgdboc(); 137 return configure_kgdboc();
89} 138}
90 139
91static void cleanup_kgdboc(void)
92{
93 if (configured == 1)
94 kgdb_unregister_io_module(&kgdboc_io_ops);
95}
96
97static int kgdboc_get_char(void) 140static int kgdboc_get_char(void)
98{ 141{
142 if (!kgdb_tty_driver)
143 return -1;
99 return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver, 144 return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
100 kgdb_tty_line); 145 kgdb_tty_line);
101} 146}
102 147
103static void kgdboc_put_char(u8 chr) 148static void kgdboc_put_char(u8 chr)
104{ 149{
150 if (!kgdb_tty_driver)
151 return;
105 kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver, 152 kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
106 kgdb_tty_line, chr); 153 kgdb_tty_line, chr);
107} 154}