diff options
| author | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:22 -0400 |
|---|---|---|
| committer | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:22 -0400 |
| commit | f5316b4aea024da9266d740322a5481657f6ce59 (patch) | |
| tree | 5888fd0afa54fc3bab2711e583147c4b563836bc /kernel/debug | |
| parent | dcc7871128e99458ca86186b7bc8bf27ff0c47b5 (diff) | |
kgdb,8250,pl011: Return immediately from console poll
The design of the kdb shell requires that every device that can
provide input to kdb have a polling routine that exits immediately if
there is no character available. This is required in order to get the
page scrolling mechanism working.
Changing the kernel debugger I/O API to require all polling character
routines to exit immediately if there is no data allows the kernel
debugger to process multiple input channels.
NO_POLL_CHAR will be the return code to the polling routine when ever
there is no character available.
CC: linux-serial@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug')
| -rw-r--r-- | kernel/debug/debug_core.c | 2 | ||||
| -rw-r--r-- | kernel/debug/gdbstub.c | 37 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_debugger.c | 10 |
3 files changed, 43 insertions, 6 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 6e1fa829fdeb..1d71df66f3fa 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
| @@ -882,6 +882,8 @@ EXPORT_SYMBOL_GPL(kgdb_unregister_io_module); | |||
| 882 | int dbg_io_get_char(void) | 882 | int dbg_io_get_char(void) |
| 883 | { | 883 | { |
| 884 | int ret = dbg_io_ops->read_char(); | 884 | int ret = dbg_io_ops->read_char(); |
| 885 | if (ret == NO_POLL_CHAR) | ||
| 886 | return -1; | ||
| 885 | if (!dbg_kdb_mode) | 887 | if (!dbg_kdb_mode) |
| 886 | return ret; | 888 | return ret; |
| 887 | if (ret == 127) | 889 | if (ret == 127) |
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 188203a19657..3c000490a7dd 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 32 | #include <linux/kgdb.h> | 32 | #include <linux/kgdb.h> |
| 33 | #include <linux/kdb.h> | ||
| 33 | #include <linux/reboot.h> | 34 | #include <linux/reboot.h> |
| 34 | #include <linux/uaccess.h> | 35 | #include <linux/uaccess.h> |
| 35 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
| @@ -62,6 +63,30 @@ static int hex(char ch) | |||
| 62 | return -1; | 63 | return -1; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 66 | #ifdef CONFIG_KGDB_KDB | ||
| 67 | static int gdbstub_read_wait(void) | ||
| 68 | { | ||
| 69 | int ret = -1; | ||
| 70 | int i; | ||
| 71 | |||
| 72 | /* poll any additional I/O interfaces that are defined */ | ||
| 73 | while (ret < 0) | ||
| 74 | for (i = 0; kdb_poll_funcs[i] != NULL; i++) { | ||
| 75 | ret = kdb_poll_funcs[i](); | ||
| 76 | if (ret > 0) | ||
| 77 | break; | ||
| 78 | } | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | #else | ||
| 82 | static int gdbstub_read_wait(void) | ||
| 83 | { | ||
| 84 | int ret = dbg_io_ops->read_char(); | ||
| 85 | while (ret == NO_POLL_CHAR) | ||
| 86 | ret = dbg_io_ops->read_char(); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | #endif | ||
| 65 | /* scan for the sequence $<data>#<checksum> */ | 90 | /* scan for the sequence $<data>#<checksum> */ |
| 66 | static void get_packet(char *buffer) | 91 | static void get_packet(char *buffer) |
| 67 | { | 92 | { |
| @@ -75,7 +100,7 @@ static void get_packet(char *buffer) | |||
| 75 | * Spin and wait around for the start character, ignore all | 100 | * Spin and wait around for the start character, ignore all |
| 76 | * other characters: | 101 | * other characters: |
| 77 | */ | 102 | */ |
| 78 | while ((ch = (dbg_io_ops->read_char())) != '$') | 103 | while ((ch = (gdbstub_read_wait())) != '$') |
| 79 | /* nothing */; | 104 | /* nothing */; |
| 80 | 105 | ||
| 81 | kgdb_connected = 1; | 106 | kgdb_connected = 1; |
| @@ -88,7 +113,7 @@ static void get_packet(char *buffer) | |||
| 88 | * now, read until a # or end of buffer is found: | 113 | * now, read until a # or end of buffer is found: |
| 89 | */ | 114 | */ |
| 90 | while (count < (BUFMAX - 1)) { | 115 | while (count < (BUFMAX - 1)) { |
| 91 | ch = dbg_io_ops->read_char(); | 116 | ch = gdbstub_read_wait(); |
| 92 | if (ch == '#') | 117 | if (ch == '#') |
| 93 | break; | 118 | break; |
| 94 | checksum = checksum + ch; | 119 | checksum = checksum + ch; |
| @@ -98,8 +123,8 @@ static void get_packet(char *buffer) | |||
| 98 | buffer[count] = 0; | 123 | buffer[count] = 0; |
| 99 | 124 | ||
| 100 | if (ch == '#') { | 125 | if (ch == '#') { |
| 101 | xmitcsum = hex(dbg_io_ops->read_char()) << 4; | 126 | xmitcsum = hex(gdbstub_read_wait()) << 4; |
| 102 | xmitcsum += hex(dbg_io_ops->read_char()); | 127 | xmitcsum += hex(gdbstub_read_wait()); |
| 103 | 128 | ||
| 104 | if (checksum != xmitcsum) | 129 | if (checksum != xmitcsum) |
| 105 | /* failed checksum */ | 130 | /* failed checksum */ |
| @@ -144,10 +169,10 @@ static void put_packet(char *buffer) | |||
| 144 | dbg_io_ops->flush(); | 169 | dbg_io_ops->flush(); |
| 145 | 170 | ||
| 146 | /* Now see what we get in reply. */ | 171 | /* Now see what we get in reply. */ |
| 147 | ch = dbg_io_ops->read_char(); | 172 | ch = gdbstub_read_wait(); |
| 148 | 173 | ||
| 149 | if (ch == 3) | 174 | if (ch == 3) |
| 150 | ch = dbg_io_ops->read_char(); | 175 | ch = gdbstub_read_wait(); |
| 151 | 176 | ||
| 152 | /* If we get an ACK, we are done. */ | 177 | /* If we get an ACK, we are done. */ |
| 153 | if (ch == '+') | 178 | if (ch == '+') |
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c index f024c0c4b8c4..bf6e8270e957 100644 --- a/kernel/debug/kdb/kdb_debugger.c +++ b/kernel/debug/kdb/kdb_debugger.c | |||
| @@ -20,7 +20,15 @@ | |||
| 20 | get_char_func kdb_poll_funcs[] = { | 20 | get_char_func kdb_poll_funcs[] = { |
| 21 | dbg_io_get_char, | 21 | dbg_io_get_char, |
| 22 | NULL, | 22 | NULL, |
| 23 | NULL, | ||
| 24 | NULL, | ||
| 25 | NULL, | ||
| 26 | NULL, | ||
| 23 | }; | 27 | }; |
| 28 | EXPORT_SYMBOL_GPL(kdb_poll_funcs); | ||
| 29 | |||
| 30 | int kdb_poll_idx = 1; | ||
| 31 | EXPORT_SYMBOL_GPL(kdb_poll_idx); | ||
| 24 | 32 | ||
| 25 | int kdb_stub(struct kgdb_state *ks) | 33 | int kdb_stub(struct kgdb_state *ks) |
| 26 | { | 34 | { |
| @@ -85,6 +93,7 @@ int kdb_stub(struct kgdb_state *ks) | |||
| 85 | kdb_bp_remove(); | 93 | kdb_bp_remove(); |
| 86 | KDB_STATE_CLEAR(DOING_SS); | 94 | KDB_STATE_CLEAR(DOING_SS); |
| 87 | KDB_STATE_CLEAR(DOING_SSB); | 95 | KDB_STATE_CLEAR(DOING_SSB); |
| 96 | KDB_STATE_SET(PAGER); | ||
| 88 | /* zero out any offline cpu data */ | 97 | /* zero out any offline cpu data */ |
| 89 | for_each_present_cpu(i) { | 98 | for_each_present_cpu(i) { |
| 90 | if (!cpu_online(i)) { | 99 | if (!cpu_online(i)) { |
| @@ -112,6 +121,7 @@ int kdb_stub(struct kgdb_state *ks) | |||
| 112 | kdb_initial_cpu = -1; | 121 | kdb_initial_cpu = -1; |
| 113 | kdb_current_task = NULL; | 122 | kdb_current_task = NULL; |
| 114 | kdb_current_regs = NULL; | 123 | kdb_current_regs = NULL; |
| 124 | KDB_STATE_CLEAR(PAGER); | ||
| 115 | kdbnearsym_cleanup(); | 125 | kdbnearsym_cleanup(); |
| 116 | if (error == KDB_CMD_KGDB) { | 126 | if (error == KDB_CMD_KGDB) { |
| 117 | if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { | 127 | if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { |
