aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:22 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-05-20 22:04:22 -0400
commitf5316b4aea024da9266d740322a5481657f6ce59 (patch)
tree5888fd0afa54fc3bab2711e583147c4b563836bc
parentdcc7871128e99458ca86186b7bc8bf27ff0c47b5 (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.c4
-rw-r--r--drivers/serial/amba-pl011.c6
-rw-r--r--include/linux/kdb.h1
-rw-r--r--include/linux/serial_core.h1
-rw-r--r--kernel/debug/debug_core.c2
-rw-r--r--kernel/debug/gdbstub.c37
-rw-r--r--kernel/debug/kdb/kdb_debugger.c10
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
22extern 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);
882int dbg_io_get_char(void) 882int 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
67static 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
82static 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> */
66static void get_packet(char *buffer) 91static 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 @@
20get_char_func kdb_poll_funcs[] = { 20get_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};
28EXPORT_SYMBOL_GPL(kdb_poll_funcs);
29
30int kdb_poll_idx = 1;
31EXPORT_SYMBOL_GPL(kdb_poll_idx);
24 32
25int kdb_stub(struct kgdb_state *ks) 33int 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)) {