summaryrefslogtreecommitdiff
path: root/kernel/debug/gdbstub.c
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-05-20 21:04:22 -0500
committerJason Wessel <jason.wessel@windriver.com>2010-05-20 21:04:22 -0500
commitf5316b4aea024da9266d740322a5481657f6ce59 (patch)
tree5888fd0afa54fc3bab2711e583147c4b563836bc /kernel/debug/gdbstub.c
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>
Diffstat (limited to 'kernel/debug/gdbstub.c')
-rw-r--r--kernel/debug/gdbstub.c37
1 files changed, 31 insertions, 6 deletions
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 @@
#include <linux/kernel.h>
#include <linux/kgdb.h>
+#include <linux/kdb.h>
#include <linux/reboot.h>
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
@@ -62,6 +63,30 @@ static int hex(char ch)
return -1;
}
+#ifdef CONFIG_KGDB_KDB
+static int gdbstub_read_wait(void)
+{
+ int ret = -1;
+ int i;
+
+ /* poll any additional I/O interfaces that are defined */
+ while (ret < 0)
+ for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
+ ret = kdb_poll_funcs[i]();
+ if (ret > 0)
+ break;
+ }
+ return ret;
+}
+#else
+static int gdbstub_read_wait(void)
+{
+ int ret = dbg_io_ops->read_char();
+ while (ret == NO_POLL_CHAR)
+ ret = dbg_io_ops->read_char();
+ return ret;
+}
+#endif
/* scan for the sequence $<data>#<checksum> */
static void get_packet(char *buffer)
{
@@ -75,7 +100,7 @@ static void get_packet(char *buffer)
* Spin and wait around for the start character, ignore all
* other characters:
*/
- while ((ch = (dbg_io_ops->read_char())) != '$')
+ while ((ch = (gdbstub_read_wait())) != '$')
/* nothing */;
kgdb_connected = 1;
@@ -88,7 +113,7 @@ static void get_packet(char *buffer)
* now, read until a # or end of buffer is found:
*/
while (count < (BUFMAX - 1)) {
- ch = dbg_io_ops->read_char();
+ ch = gdbstub_read_wait();
if (ch == '#')
break;
checksum = checksum + ch;
@@ -98,8 +123,8 @@ static void get_packet(char *buffer)
buffer[count] = 0;
if (ch == '#') {
- xmitcsum = hex(dbg_io_ops->read_char()) << 4;
- xmitcsum += hex(dbg_io_ops->read_char());
+ xmitcsum = hex(gdbstub_read_wait()) << 4;
+ xmitcsum += hex(gdbstub_read_wait());
if (checksum != xmitcsum)
/* failed checksum */
@@ -144,10 +169,10 @@ static void put_packet(char *buffer)
dbg_io_ops->flush();
/* Now see what we get in reply. */
- ch = dbg_io_ops->read_char();
+ ch = gdbstub_read_wait();
if (ch == 3)
- ch = dbg_io_ops->read_char();
+ ch = gdbstub_read_wait();
/* If we get an ACK, we are done. */
if (ch == '+')