diff options
| -rw-r--r-- | Documentation/kernel-parameters.txt | 11 | ||||
| -rw-r--r-- | drivers/usb/early/ehci-dbgp.c | 120 |
2 files changed, 122 insertions, 9 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4c44d01c67f4..f5fce483930c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1127,6 +1127,17 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1127 | use the HighMem zone if it exists, and the Normal | 1127 | use the HighMem zone if it exists, and the Normal |
| 1128 | zone if it does not. | 1128 | zone if it does not. |
| 1129 | 1129 | ||
| 1130 | kgdbdbgp= [KGDB,HW] kgdb over EHCI usb debug port. | ||
| 1131 | Format: <Controller#>[,poll interval] | ||
| 1132 | The controller # is the number of the ehci usb debug | ||
| 1133 | port as it is probed via PCI. The poll interval is | ||
| 1134 | optional and is the number seconds in between | ||
| 1135 | each poll cycle to the debug port in case you need | ||
| 1136 | the functionality for interrupting the kernel with | ||
| 1137 | gdb or control-c on the dbgp connection. When | ||
| 1138 | not using this parameter you use sysrq-g to break into | ||
| 1139 | the kernel debugger. | ||
| 1140 | |||
| 1130 | kgdboc= [KGDB,HW] kgdb over consoles. | 1141 | kgdboc= [KGDB,HW] kgdb over consoles. |
| 1131 | Requires a tty driver that supports console polling, | 1142 | Requires a tty driver that supports console polling, |
| 1132 | or a supported polling keyboard driver (non-usb). | 1143 | or a supported polling keyboard driver (non-usb). |
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 6e98a3697844..94ecdbc758ce 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c | |||
| @@ -19,6 +19,9 @@ | |||
| 19 | #include <linux/usb/ch9.h> | 19 | #include <linux/usb/ch9.h> |
| 20 | #include <linux/usb/ehci_def.h> | 20 | #include <linux/usb/ehci_def.h> |
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/serial_core.h> | ||
| 23 | #include <linux/kgdb.h> | ||
| 24 | #include <linux/kthread.h> | ||
| 22 | #include <asm/io.h> | 25 | #include <asm/io.h> |
| 23 | #include <asm/pci-direct.h> | 26 | #include <asm/pci-direct.h> |
| 24 | #include <asm/fixmap.h> | 27 | #include <asm/fixmap.h> |
| @@ -55,6 +58,7 @@ static struct ehci_regs __iomem *ehci_regs; | |||
| 55 | static struct ehci_dbg_port __iomem *ehci_debug; | 58 | static struct ehci_dbg_port __iomem *ehci_debug; |
| 56 | static int dbgp_not_safe; /* Cannot use debug device during ehci reset */ | 59 | static int dbgp_not_safe; /* Cannot use debug device during ehci reset */ |
| 57 | static unsigned int dbgp_endpoint_out; | 60 | static unsigned int dbgp_endpoint_out; |
| 61 | static unsigned int dbgp_endpoint_in; | ||
| 58 | 62 | ||
| 59 | struct ehci_dev { | 63 | struct ehci_dev { |
| 60 | u32 bus; | 64 | u32 bus; |
| @@ -91,6 +95,13 @@ static inline u32 dbgp_len_update(u32 x, u32 len) | |||
| 91 | return (x & ~0x0f) | (len & 0x0f); | 95 | return (x & ~0x0f) | (len & 0x0f); |
| 92 | } | 96 | } |
| 93 | 97 | ||
| 98 | #ifdef CONFIG_KGDB | ||
| 99 | static struct kgdb_io kgdbdbgp_io_ops; | ||
| 100 | #define dbgp_kgdb_mode (dbg_io_ops == &kgdbdbgp_io_ops) | ||
| 101 | #else | ||
| 102 | #define dbgp_kgdb_mode (0) | ||
| 103 | #endif | ||
| 104 | |||
| 94 | /* | 105 | /* |
| 95 | * USB Packet IDs (PIDs) | 106 | * USB Packet IDs (PIDs) |
| 96 | */ | 107 | */ |
| @@ -182,11 +193,10 @@ static void dbgp_breath(void) | |||
| 182 | /* Sleep to give the debug port a chance to breathe */ | 193 | /* Sleep to give the debug port a chance to breathe */ |
| 183 | } | 194 | } |
| 184 | 195 | ||
| 185 | static int dbgp_wait_until_done(unsigned ctrl) | 196 | static int dbgp_wait_until_done(unsigned ctrl, int loop) |
| 186 | { | 197 | { |
| 187 | u32 pids, lpid; | 198 | u32 pids, lpid; |
| 188 | int ret; | 199 | int ret; |
| 189 | int loop = DBGP_LOOPS; | ||
| 190 | 200 | ||
| 191 | retry: | 201 | retry: |
| 192 | writel(ctrl | DBGP_GO, &ehci_debug->control); | 202 | writel(ctrl | DBGP_GO, &ehci_debug->control); |
| @@ -276,13 +286,13 @@ static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, | |||
| 276 | dbgp_set_data(bytes, size); | 286 | dbgp_set_data(bytes, size); |
| 277 | writel(addr, &ehci_debug->address); | 287 | writel(addr, &ehci_debug->address); |
| 278 | writel(pids, &ehci_debug->pids); | 288 | writel(pids, &ehci_debug->pids); |
| 279 | ret = dbgp_wait_until_done(ctrl); | 289 | ret = dbgp_wait_until_done(ctrl, DBGP_LOOPS); |
| 280 | 290 | ||
| 281 | return ret; | 291 | return ret; |
| 282 | } | 292 | } |
| 283 | 293 | ||
| 284 | static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, | 294 | static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, |
| 285 | int size) | 295 | int size, int loops) |
| 286 | { | 296 | { |
| 287 | u32 pids, addr, ctrl; | 297 | u32 pids, addr, ctrl; |
| 288 | int ret; | 298 | int ret; |
| @@ -302,7 +312,7 @@ static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, | |||
| 302 | 312 | ||
| 303 | writel(addr, &ehci_debug->address); | 313 | writel(addr, &ehci_debug->address); |
| 304 | writel(pids, &ehci_debug->pids); | 314 | writel(pids, &ehci_debug->pids); |
| 305 | ret = dbgp_wait_until_done(ctrl); | 315 | ret = dbgp_wait_until_done(ctrl, loops); |
| 306 | if (ret < 0) | 316 | if (ret < 0) |
| 307 | return ret; | 317 | return ret; |
| 308 | 318 | ||
| @@ -343,12 +353,12 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, | |||
| 343 | dbgp_set_data(&req, sizeof(req)); | 353 | dbgp_set_data(&req, sizeof(req)); |
| 344 | writel(addr, &ehci_debug->address); | 354 | writel(addr, &ehci_debug->address); |
| 345 | writel(pids, &ehci_debug->pids); | 355 | writel(pids, &ehci_debug->pids); |
| 346 | ret = dbgp_wait_until_done(ctrl); | 356 | ret = dbgp_wait_until_done(ctrl, DBGP_LOOPS); |
| 347 | if (ret < 0) | 357 | if (ret < 0) |
| 348 | return ret; | 358 | return ret; |
| 349 | 359 | ||
| 350 | /* Read the result */ | 360 | /* Read the result */ |
| 351 | return dbgp_bulk_read(devnum, 0, data, size); | 361 | return dbgp_bulk_read(devnum, 0, data, size, DBGP_LOOPS); |
| 352 | } | 362 | } |
| 353 | 363 | ||
| 354 | /* Find a PCI capability */ | 364 | /* Find a PCI capability */ |
| @@ -559,6 +569,7 @@ try_again: | |||
| 559 | goto err; | 569 | goto err; |
| 560 | } | 570 | } |
| 561 | dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; | 571 | dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; |
| 572 | dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint; | ||
| 562 | 573 | ||
| 563 | /* Move the device to 127 if it isn't already there */ | 574 | /* Move the device to 127 if it isn't already there */ |
| 564 | if (devnum != USB_DEBUG_DEVNUM) { | 575 | if (devnum != USB_DEBUG_DEVNUM) { |
| @@ -968,8 +979,9 @@ int dbgp_reset_prep(void) | |||
| 968 | if (!ehci_debug) | 979 | if (!ehci_debug) |
| 969 | return 0; | 980 | return 0; |
| 970 | 981 | ||
| 971 | if (early_dbgp_console.index != -1 && | 982 | if ((early_dbgp_console.index != -1 && |
| 972 | !(early_dbgp_console.flags & CON_BOOT)) | 983 | !(early_dbgp_console.flags & CON_BOOT)) || |
| 984 | dbgp_kgdb_mode) | ||
| 973 | return 1; | 985 | return 1; |
| 974 | /* This means the console is not initialized, or should get | 986 | /* This means the console is not initialized, or should get |
| 975 | * shutdown so as to allow for reuse of the usb device, which | 987 | * shutdown so as to allow for reuse of the usb device, which |
| @@ -982,3 +994,93 @@ int dbgp_reset_prep(void) | |||
| 982 | return 0; | 994 | return 0; |
| 983 | } | 995 | } |
| 984 | EXPORT_SYMBOL_GPL(dbgp_reset_prep); | 996 | EXPORT_SYMBOL_GPL(dbgp_reset_prep); |
| 997 | |||
| 998 | #ifdef CONFIG_KGDB | ||
| 999 | |||
| 1000 | static char kgdbdbgp_buf[DBGP_MAX_PACKET]; | ||
| 1001 | static int kgdbdbgp_buf_sz; | ||
| 1002 | static int kgdbdbgp_buf_idx; | ||
| 1003 | static int kgdbdbgp_loop_cnt = DBGP_LOOPS; | ||
| 1004 | |||
| 1005 | static int kgdbdbgp_read_char(void) | ||
| 1006 | { | ||
| 1007 | int ret; | ||
| 1008 | |||
| 1009 | if (kgdbdbgp_buf_idx < kgdbdbgp_buf_sz) { | ||
| 1010 | char ch = kgdbdbgp_buf[kgdbdbgp_buf_idx++]; | ||
| 1011 | return ch; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | ret = dbgp_bulk_read(USB_DEBUG_DEVNUM, dbgp_endpoint_in, | ||
| 1015 | &kgdbdbgp_buf, DBGP_MAX_PACKET, | ||
| 1016 | kgdbdbgp_loop_cnt); | ||
| 1017 | if (ret <= 0) | ||
| 1018 | return NO_POLL_CHAR; | ||
| 1019 | kgdbdbgp_buf_sz = ret; | ||
| 1020 | kgdbdbgp_buf_idx = 1; | ||
| 1021 | return kgdbdbgp_buf[0]; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | static void kgdbdbgp_write_char(u8 chr) | ||
| 1025 | { | ||
| 1026 | early_dbgp_write(NULL, &chr, 1); | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | static struct kgdb_io kgdbdbgp_io_ops = { | ||
| 1030 | .name = "kgdbdbgp", | ||
| 1031 | .read_char = kgdbdbgp_read_char, | ||
| 1032 | .write_char = kgdbdbgp_write_char, | ||
| 1033 | }; | ||
| 1034 | |||
| 1035 | static int kgdbdbgp_wait_time; | ||
| 1036 | |||
| 1037 | static int __init kgdbdbgp_parse_config(char *str) | ||
| 1038 | { | ||
| 1039 | char *ptr; | ||
| 1040 | |||
| 1041 | if (!ehci_debug) { | ||
| 1042 | if (early_dbgp_init(str)) | ||
| 1043 | return -1; | ||
| 1044 | } | ||
| 1045 | ptr = strchr(str, ','); | ||
| 1046 | if (ptr) { | ||
| 1047 | ptr++; | ||
| 1048 | kgdbdbgp_wait_time = simple_strtoul(ptr, &ptr, 10); | ||
| 1049 | } | ||
| 1050 | kgdb_register_io_module(&kgdbdbgp_io_ops); | ||
| 1051 | kgdbdbgp_io_ops.is_console = early_dbgp_console.index != -1; | ||
| 1052 | |||
| 1053 | return 0; | ||
| 1054 | } | ||
| 1055 | early_param("kgdbdbgp", kgdbdbgp_parse_config); | ||
| 1056 | |||
| 1057 | static int kgdbdbgp_reader_thread(void *ptr) | ||
| 1058 | { | ||
| 1059 | int ret; | ||
| 1060 | |||
| 1061 | while (readl(&ehci_debug->control) & DBGP_ENABLED) { | ||
| 1062 | kgdbdbgp_loop_cnt = 1; | ||
| 1063 | ret = kgdbdbgp_read_char(); | ||
| 1064 | kgdbdbgp_loop_cnt = DBGP_LOOPS; | ||
| 1065 | if (ret != NO_POLL_CHAR) { | ||
| 1066 | if (ret == 0x3 || ret == '$') { | ||
| 1067 | if (ret == '$') | ||
| 1068 | kgdbdbgp_buf_idx--; | ||
| 1069 | kgdb_breakpoint(); | ||
| 1070 | } | ||
| 1071 | continue; | ||
| 1072 | } | ||
| 1073 | schedule_timeout_interruptible(kgdbdbgp_wait_time * HZ); | ||
| 1074 | } | ||
| 1075 | return 0; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static int __init kgdbdbgp_start_thread(void) | ||
| 1079 | { | ||
| 1080 | if (dbgp_kgdb_mode && kgdbdbgp_wait_time) | ||
| 1081 | kthread_run(kgdbdbgp_reader_thread, NULL, "%s", "dbgp"); | ||
| 1082 | |||
| 1083 | return 0; | ||
| 1084 | } | ||
| 1085 | module_init(kgdbdbgp_start_thread); | ||
| 1086 | #endif /* CONFIG_KGDB */ | ||
