diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 14:08:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 14:08:05 -0400 |
commit | 90b9a32d8f441369b2f97a765d2d957b531eb653 (patch) | |
tree | 3146d251a983ba12226e75c121613de6f051af8b /drivers/serial | |
parent | 8b108c609adefd98577c35f0a41497a610041a6c (diff) | |
parent | 4402c153cb9c549cd21d6007ef0dfac50c8d148d (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.c | 4 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 6 | ||||
-rw-r--r-- | drivers/serial/kgdboc.c | 75 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 6 | ||||
-rw-r--r-- | drivers/serial/sunzilog.c | 50 |
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 = { | |||
32 | static struct tty_driver *kgdb_tty_driver; | 34 | static struct tty_driver *kgdb_tty_driver; |
33 | static int kgdb_tty_line; | 35 | static int kgdb_tty_line; |
34 | 36 | ||
37 | #ifdef CONFIG_KDB_KEYBOARD | ||
38 | static 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 | |||
53 | static 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 | |||
35 | static int kgdboc_option_setup(char *opt) | 71 | static 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 | ||
84 | static void cleanup_kgdboc(void) | ||
85 | { | ||
86 | kgdboc_unregister_kbd(); | ||
87 | if (configured == 1) | ||
88 | kgdb_unregister_io_module(&kgdboc_io_ops); | ||
89 | } | ||
90 | |||
48 | static int configure_kgdboc(void) | 91 | static 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 | ||
128 | do_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) | |||
75 | noconfig: | 137 | noconfig: |
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 | ||
91 | static void cleanup_kgdboc(void) | ||
92 | { | ||
93 | if (configured == 1) | ||
94 | kgdb_unregister_io_module(&kgdboc_io_ops); | ||
95 | } | ||
96 | |||
97 | static int kgdboc_get_char(void) | 154 | static 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 | ||
103 | static void kgdboc_put_char(u8 chr) | 162 | static 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 | ||
105 | static 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 | ||
1002 | static 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 | |||
1036 | static 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 | |||
999 | static struct uart_ops sunzilog_pops = { | 1045 | static 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 | ||
1018 | static int uart_chip_count; | 1068 | static int uart_chip_count; |