Commit f5316b4a authored by Jason Wessel's avatar Jason Wessel

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: default avatarJason Wessel <jason.wessel@windriver.com>
parent dcc78711
...@@ -1891,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port) ...@@ -1891,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port)
struct uart_8250_port *up = (struct uart_8250_port *)port; struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char lsr = serial_inp(up, UART_LSR); unsigned char lsr = serial_inp(up, UART_LSR);
while (!(lsr & UART_LSR_DR)) if (!(lsr & UART_LSR_DR))
lsr = serial_inp(up, UART_LSR); return NO_POLL_CHAR;
return serial_inp(up, UART_RX); return serial_inp(up, UART_RX);
} }
......
...@@ -342,9 +342,9 @@ static int pl010_get_poll_char(struct uart_port *port) ...@@ -342,9 +342,9 @@ static int pl010_get_poll_char(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port; struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status; unsigned int status;
do {
status = readw(uap->port.membase + UART01x_FR); status = readw(uap->port.membase + UART01x_FR);
} while (status & UART01x_FR_RXFE); if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR;
return readw(uap->port.membase + UART01x_DR); return readw(uap->port.membase + UART01x_DR);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#define KDB_POLL_FUNC_MAX 5 #define KDB_POLL_FUNC_MAX 5
extern int kdb_poll_idx;
/* /*
* kdb_initial_cpu is initialized to -1, and is set to the cpu * kdb_initial_cpu is initialized to -1, and is set to the cpu
......
...@@ -246,6 +246,7 @@ struct uart_ops { ...@@ -246,6 +246,7 @@ struct uart_ops {
#endif #endif
}; };
#define NO_POLL_CHAR 0x00ff0000
#define UART_CONFIG_TYPE (1 << 0) #define UART_CONFIG_TYPE (1 << 0)
#define UART_CONFIG_IRQ (1 << 1) #define UART_CONFIG_IRQ (1 << 1)
......
...@@ -882,6 +882,8 @@ EXPORT_SYMBOL_GPL(kgdb_unregister_io_module); ...@@ -882,6 +882,8 @@ EXPORT_SYMBOL_GPL(kgdb_unregister_io_module);
int dbg_io_get_char(void) int dbg_io_get_char(void)
{ {
int ret = dbg_io_ops->read_char(); int ret = dbg_io_ops->read_char();
if (ret == NO_POLL_CHAR)
return -1;
if (!dbg_kdb_mode) if (!dbg_kdb_mode)
return ret; return ret;
if (ret == 127) if (ret == 127)
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kgdb.h> #include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -62,6 +63,30 @@ static int hex(char ch) ...@@ -62,6 +63,30 @@ static int hex(char ch)
return -1; 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> */ /* scan for the sequence $<data>#<checksum> */
static void get_packet(char *buffer) static void get_packet(char *buffer)
{ {
...@@ -75,7 +100,7 @@ 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 * Spin and wait around for the start character, ignore all
* other characters: * other characters:
*/ */
while ((ch = (dbg_io_ops->read_char())) != '$') while ((ch = (gdbstub_read_wait())) != '$')
/* nothing */; /* nothing */;
kgdb_connected = 1; kgdb_connected = 1;
...@@ -88,7 +113,7 @@ static void get_packet(char *buffer) ...@@ -88,7 +113,7 @@ static void get_packet(char *buffer)
* now, read until a # or end of buffer is found: * now, read until a # or end of buffer is found:
*/ */
while (count < (BUFMAX - 1)) { while (count < (BUFMAX - 1)) {
ch = dbg_io_ops->read_char(); ch = gdbstub_read_wait();
if (ch == '#') if (ch == '#')
break; break;
checksum = checksum + ch; checksum = checksum + ch;
...@@ -98,8 +123,8 @@ static void get_packet(char *buffer) ...@@ -98,8 +123,8 @@ static void get_packet(char *buffer)
buffer[count] = 0; buffer[count] = 0;
if (ch == '#') { if (ch == '#') {
xmitcsum = hex(dbg_io_ops->read_char()) << 4; xmitcsum = hex(gdbstub_read_wait()) << 4;
xmitcsum += hex(dbg_io_ops->read_char()); xmitcsum += hex(gdbstub_read_wait());
if (checksum != xmitcsum) if (checksum != xmitcsum)
/* failed checksum */ /* failed checksum */
...@@ -144,10 +169,10 @@ static void put_packet(char *buffer) ...@@ -144,10 +169,10 @@ static void put_packet(char *buffer)
dbg_io_ops->flush(); dbg_io_ops->flush();
/* Now see what we get in reply. */ /* Now see what we get in reply. */
ch = dbg_io_ops->read_char(); ch = gdbstub_read_wait();
if (ch == 3) if (ch == 3)
ch = dbg_io_ops->read_char(); ch = gdbstub_read_wait();
/* If we get an ACK, we are done. */ /* If we get an ACK, we are done. */
if (ch == '+') if (ch == '+')
......
...@@ -20,7 +20,15 @@ ...@@ -20,7 +20,15 @@
get_char_func kdb_poll_funcs[] = { get_char_func kdb_poll_funcs[] = {
dbg_io_get_char, dbg_io_get_char,
NULL, NULL,
NULL,
NULL,
NULL,
NULL,
}; };
EXPORT_SYMBOL_GPL(kdb_poll_funcs);
int kdb_poll_idx = 1;
EXPORT_SYMBOL_GPL(kdb_poll_idx);
int kdb_stub(struct kgdb_state *ks) int kdb_stub(struct kgdb_state *ks)
{ {
...@@ -85,6 +93,7 @@ int kdb_stub(struct kgdb_state *ks) ...@@ -85,6 +93,7 @@ int kdb_stub(struct kgdb_state *ks)
kdb_bp_remove(); kdb_bp_remove();
KDB_STATE_CLEAR(DOING_SS); KDB_STATE_CLEAR(DOING_SS);
KDB_STATE_CLEAR(DOING_SSB); KDB_STATE_CLEAR(DOING_SSB);
KDB_STATE_SET(PAGER);
/* zero out any offline cpu data */ /* zero out any offline cpu data */
for_each_present_cpu(i) { for_each_present_cpu(i) {
if (!cpu_online(i)) { if (!cpu_online(i)) {
...@@ -112,6 +121,7 @@ int kdb_stub(struct kgdb_state *ks) ...@@ -112,6 +121,7 @@ int kdb_stub(struct kgdb_state *ks)
kdb_initial_cpu = -1; kdb_initial_cpu = -1;
kdb_current_task = NULL; kdb_current_task = NULL;
kdb_current_regs = NULL; kdb_current_regs = NULL;
KDB_STATE_CLEAR(PAGER);
kdbnearsym_cleanup(); kdbnearsym_cleanup();
if (error == KDB_CMD_KGDB) { if (error == KDB_CMD_KGDB) {
if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment