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 | |
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>
-rw-r--r-- | drivers/serial/8250.c | 4 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 6 | ||||
-rw-r--r-- | include/linux/kdb.h | 1 | ||||
-rw-r--r-- | include/linux/serial_core.h | 1 | ||||
-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 |
7 files changed, 50 insertions, 11 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 2b1ea3d4c4f4..891e1dd65f24 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1891,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port) | |||
1891 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1891 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1892 | unsigned char lsr = serial_inp(up, UART_LSR); | 1892 | unsigned char lsr = serial_inp(up, UART_LSR); |
1893 | 1893 | ||
1894 | while (!(lsr & UART_LSR_DR)) | 1894 | if (!(lsr & UART_LSR_DR)) |
1895 | lsr = serial_inp(up, UART_LSR); | 1895 | return NO_POLL_CHAR; |
1896 | 1896 | ||
1897 | return serial_inp(up, UART_RX); | 1897 | return serial_inp(up, UART_RX); |
1898 | } | 1898 | } |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 743ebf5f16da..eb4cb480b93e 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -342,9 +342,9 @@ static int pl010_get_poll_char(struct uart_port *port) | |||
342 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 342 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
343 | unsigned int status; | 343 | unsigned int status; |
344 | 344 | ||
345 | do { | 345 | status = readw(uap->port.membase + UART01x_FR); |
346 | status = readw(uap->port.membase + UART01x_FR); | 346 | if (status & UART01x_FR_RXFE) |
347 | } while (status & UART01x_FR_RXFE); | 347 | return NO_POLL_CHAR; |
348 | 348 | ||
349 | return readw(uap->port.membase + UART01x_DR); | 349 | return readw(uap->port.membase + UART01x_DR); |
350 | } | 350 | } |
diff --git a/include/linux/kdb.h b/include/linux/kdb.h index 4d93790faec3..d72fa3908128 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
20 | 20 | ||
21 | #define KDB_POLL_FUNC_MAX 5 | 21 | #define KDB_POLL_FUNC_MAX 5 |
22 | extern int kdb_poll_idx; | ||
22 | 23 | ||
23 | /* | 24 | /* |
24 | * kdb_initial_cpu is initialized to -1, and is set to the cpu | 25 | * kdb_initial_cpu is initialized to -1, and is set to the cpu |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 78dd1e7120a9..ad839963fa68 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -246,6 +246,7 @@ struct uart_ops { | |||
246 | #endif | 246 | #endif |
247 | }; | 247 | }; |
248 | 248 | ||
249 | #define NO_POLL_CHAR 0x00ff0000 | ||
249 | #define UART_CONFIG_TYPE (1 << 0) | 250 | #define UART_CONFIG_TYPE (1 << 0) |
250 | #define UART_CONFIG_IRQ (1 << 1) | 251 | #define UART_CONFIG_IRQ (1 << 1) |
251 | 252 | ||
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)) { |