aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 14:08:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 14:08:05 -0400
commit90b9a32d8f441369b2f97a765d2d957b531eb653 (patch)
tree3146d251a983ba12226e75c121613de6f051af8b /drivers/serial
parent8b108c609adefd98577c35f0a41497a610041a6c (diff)
parent4402c153cb9c549cd21d6007ef0dfac50c8d148d (diff)
Merge branch 'kdb-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'kdb-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: (25 commits) kdb,debug_core: Allow the debug core to receive a panic notification MAINTAINERS: update kgdb, kdb, and debug_core info debug_core,kdb: Allow the debug core to process a recursive debug entry printk,kdb: capture printk() when in kdb shell kgdboc,kdb: Allow kdb to work on a non open console port kgdb: Add the ability to schedule a breakpoint via a tasklet mips,kgdb: kdb low level trap catch and stack trace powerpc,kgdb: Introduce low level trap catching x86,kgdb: Add low level debug hook kgdb: remove post_primary_code references kgdb,docs: Update the kgdb docs to include kdb kgdboc,keyboard: Keyboard driver for kdb with kgdb kgdb: gdb "monitor" -> kdb passthrough sparc,sunzilog: Add console polling support for sunzilog serial driver sh,sh-sci: Use NO_POLL_CHAR in the SCIF polled console code kgdb,8250,pl011: Return immediately from console poll kgdb: core changes to support kdb kdb: core for kgdb back end (2 of 2) kdb: core for kgdb back end (1 of 2) kgdb,blackfin: Add in kgdb_arch_set_pc for blackfin ...
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c4
-rw-r--r--drivers/serial/amba-pl011.c6
-rw-r--r--drivers/serial/kgdboc.c75
-rw-r--r--drivers/serial/sh-sci.c6
-rw-r--r--drivers/serial/sunzilog.c50
5 files changed, 128 insertions, 13 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/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index eadc1ab6bbce..b765ab48dfe7 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -14,7 +14,9 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/ctype.h> 15#include <linux/ctype.h>
16#include <linux/kgdb.h> 16#include <linux/kgdb.h>
17#include <linux/kdb.h>
17#include <linux/tty.h> 18#include <linux/tty.h>
19#include <linux/console.h>
18 20
19#define MAX_CONFIG_LEN 40 21#define MAX_CONFIG_LEN 40
20 22
@@ -32,6 +34,40 @@ static struct kparam_string kps = {
32static struct tty_driver *kgdb_tty_driver; 34static struct tty_driver *kgdb_tty_driver;
33static int kgdb_tty_line; 35static int kgdb_tty_line;
34 36
37#ifdef CONFIG_KDB_KEYBOARD
38static int kgdboc_register_kbd(char **cptr)
39{
40 if (strncmp(*cptr, "kbd", 3) == 0) {
41 if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
42 kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
43 kdb_poll_idx++;
44 if (cptr[0][3] == ',')
45 *cptr += 4;
46 else
47 return 1;
48 }
49 }
50 return 0;
51}
52
53static void kgdboc_unregister_kbd(void)
54{
55 int i;
56
57 for (i = 0; i < kdb_poll_idx; i++) {
58 if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
59 kdb_poll_idx--;
60 kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
61 kdb_poll_funcs[kdb_poll_idx] = NULL;
62 i--;
63 }
64 }
65}
66#else /* ! CONFIG_KDB_KEYBOARD */
67#define kgdboc_register_kbd(x) 0
68#define kgdboc_unregister_kbd()
69#endif /* ! CONFIG_KDB_KEYBOARD */
70
35static int kgdboc_option_setup(char *opt) 71static int kgdboc_option_setup(char *opt)
36{ 72{
37 if (strlen(opt) > MAX_CONFIG_LEN) { 73 if (strlen(opt) > MAX_CONFIG_LEN) {
@@ -45,25 +81,51 @@ static int kgdboc_option_setup(char *opt)
45 81
46__setup("kgdboc=", kgdboc_option_setup); 82__setup("kgdboc=", kgdboc_option_setup);
47 83
84static void cleanup_kgdboc(void)
85{
86 kgdboc_unregister_kbd();
87 if (configured == 1)
88 kgdb_unregister_io_module(&kgdboc_io_ops);
89}
90
48static int configure_kgdboc(void) 91static int configure_kgdboc(void)
49{ 92{
50 struct tty_driver *p; 93 struct tty_driver *p;
51 int tty_line = 0; 94 int tty_line = 0;
52 int err; 95 int err;
96 char *cptr = config;
97 struct console *cons;
53 98
54 err = kgdboc_option_setup(config); 99 err = kgdboc_option_setup(config);
55 if (err || !strlen(config) || isspace(config[0])) 100 if (err || !strlen(config) || isspace(config[0]))
56 goto noconfig; 101 goto noconfig;
57 102
58 err = -ENODEV; 103 err = -ENODEV;
104 kgdboc_io_ops.is_console = 0;
105 kgdb_tty_driver = NULL;
59 106
60 p = tty_find_polling_driver(config, &tty_line); 107 if (kgdboc_register_kbd(&cptr))
108 goto do_register;
109
110 p = tty_find_polling_driver(cptr, &tty_line);
61 if (!p) 111 if (!p)
62 goto noconfig; 112 goto noconfig;
63 113
114 cons = console_drivers;
115 while (cons) {
116 int idx;
117 if (cons->device && cons->device(cons, &idx) == p &&
118 idx == tty_line) {
119 kgdboc_io_ops.is_console = 1;
120 break;
121 }
122 cons = cons->next;
123 }
124
64 kgdb_tty_driver = p; 125 kgdb_tty_driver = p;
65 kgdb_tty_line = tty_line; 126 kgdb_tty_line = tty_line;
66 127
128do_register:
67 err = kgdb_register_io_module(&kgdboc_io_ops); 129 err = kgdb_register_io_module(&kgdboc_io_ops);
68 if (err) 130 if (err)
69 goto noconfig; 131 goto noconfig;
@@ -75,6 +137,7 @@ static int configure_kgdboc(void)
75noconfig: 137noconfig:
76 config[0] = 0; 138 config[0] = 0;
77 configured = 0; 139 configured = 0;
140 cleanup_kgdboc();
78 141
79 return err; 142 return err;
80} 143}
@@ -88,20 +151,18 @@ static int __init init_kgdboc(void)
88 return configure_kgdboc(); 151 return configure_kgdboc();
89} 152}
90 153
91static void cleanup_kgdboc(void)
92{
93 if (configured == 1)
94 kgdb_unregister_io_module(&kgdboc_io_ops);
95}
96
97static int kgdboc_get_char(void) 154static int kgdboc_get_char(void)
98{ 155{
156 if (!kgdb_tty_driver)
157 return -1;
99 return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver, 158 return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
100 kgdb_tty_line); 159 kgdb_tty_line);
101} 160}
102 161
103static void kgdboc_put_char(u8 chr) 162static void kgdboc_put_char(u8 chr)
104{ 163{
164 if (!kgdb_tty_driver)
165 return;
105 kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver, 166 kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
106 kgdb_tty_line, chr); 167 kgdb_tty_line, chr);
107} 168}
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 8d993c4cceac..f250a610a268 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -151,7 +151,11 @@ static int sci_poll_get_char(struct uart_port *port)
151 handle_error(port); 151 handle_error(port);
152 continue; 152 continue;
153 } 153 }
154 } while (!(status & SCxSR_RDxF(port))); 154 break;
155 } while (1);
156
157 if (!(status & SCxSR_RDxF(port)))
158 return NO_POLL_CHAR;
155 159
156 c = sci_in(port, SCxRDR); 160 c = sci_in(port, SCxRDR);
157 161
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 2c7a66af4f52..978b3cee02d7 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -102,6 +102,8 @@ struct uart_sunzilog_port {
102#endif 102#endif
103}; 103};
104 104
105static void sunzilog_putchar(struct uart_port *port, int ch);
106
105#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase)) 107#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
106#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT)) 108#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
107 109
@@ -996,6 +998,50 @@ static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *se
996 return -EINVAL; 998 return -EINVAL;
997} 999}
998 1000
1001#ifdef CONFIG_CONSOLE_POLL
1002static int sunzilog_get_poll_char(struct uart_port *port)
1003{
1004 unsigned char ch, r1;
1005 struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
1006 struct zilog_channel __iomem *channel
1007 = ZILOG_CHANNEL_FROM_PORT(&up->port);
1008
1009
1010 r1 = read_zsreg(channel, R1);
1011 if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
1012 writeb(ERR_RES, &channel->control);
1013 ZSDELAY();
1014 ZS_WSYNC(channel);
1015 }
1016
1017 ch = readb(&channel->control);
1018 ZSDELAY();
1019
1020 /* This funny hack depends upon BRK_ABRT not interfering
1021 * with the other bits we care about in R1.
1022 */
1023 if (ch & BRK_ABRT)
1024 r1 |= BRK_ABRT;
1025
1026 if (!(ch & Rx_CH_AV))
1027 return NO_POLL_CHAR;
1028
1029 ch = readb(&channel->data);
1030 ZSDELAY();
1031
1032 ch &= up->parity_mask;
1033 return ch;
1034}
1035
1036static void sunzilog_put_poll_char(struct uart_port *port,
1037 unsigned char ch)
1038{
1039 struct uart_sunzilog_port *up = (struct uart_sunzilog_port *)port;
1040
1041 sunzilog_putchar(&up->port, ch);
1042}
1043#endif /* CONFIG_CONSOLE_POLL */
1044
999static struct uart_ops sunzilog_pops = { 1045static struct uart_ops sunzilog_pops = {
1000 .tx_empty = sunzilog_tx_empty, 1046 .tx_empty = sunzilog_tx_empty,
1001 .set_mctrl = sunzilog_set_mctrl, 1047 .set_mctrl = sunzilog_set_mctrl,
@@ -1013,6 +1059,10 @@ static struct uart_ops sunzilog_pops = {
1013 .request_port = sunzilog_request_port, 1059 .request_port = sunzilog_request_port,
1014 .config_port = sunzilog_config_port, 1060 .config_port = sunzilog_config_port,
1015 .verify_port = sunzilog_verify_port, 1061 .verify_port = sunzilog_verify_port,
1062#ifdef CONFIG_CONSOLE_POLL
1063 .poll_get_char = sunzilog_get_poll_char,
1064 .poll_put_char = sunzilog_put_poll_char,
1065#endif
1016}; 1066};
1017 1067
1018static int uart_chip_count; 1068static int uart_chip_count;