diff options
Diffstat (limited to 'drivers/serial/kgdboc.c')
-rw-r--r-- | drivers/serial/kgdboc.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c index d4b711c9a416..3374618300af 100644 --- a/drivers/serial/kgdboc.c +++ b/drivers/serial/kgdboc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/console.h> | 19 | #include <linux/console.h> |
20 | #include <linux/vt_kern.h> | 20 | #include <linux/vt_kern.h> |
21 | #include <linux/input.h> | ||
21 | 22 | ||
22 | #define MAX_CONFIG_LEN 40 | 23 | #define MAX_CONFIG_LEN 40 |
23 | 24 | ||
@@ -37,6 +38,61 @@ static struct tty_driver *kgdb_tty_driver; | |||
37 | static int kgdb_tty_line; | 38 | static int kgdb_tty_line; |
38 | 39 | ||
39 | #ifdef CONFIG_KDB_KEYBOARD | 40 | #ifdef CONFIG_KDB_KEYBOARD |
41 | static int kgdboc_reset_connect(struct input_handler *handler, | ||
42 | struct input_dev *dev, | ||
43 | const struct input_device_id *id) | ||
44 | { | ||
45 | input_reset_device(dev); | ||
46 | |||
47 | /* Retrun an error - we do not want to bind, just to reset */ | ||
48 | return -ENODEV; | ||
49 | } | ||
50 | |||
51 | static void kgdboc_reset_disconnect(struct input_handle *handle) | ||
52 | { | ||
53 | /* We do not expect anyone to actually bind to us */ | ||
54 | BUG(); | ||
55 | } | ||
56 | |||
57 | static const struct input_device_id kgdboc_reset_ids[] = { | ||
58 | { | ||
59 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | ||
60 | .evbit = { BIT_MASK(EV_KEY) }, | ||
61 | }, | ||
62 | { } | ||
63 | }; | ||
64 | |||
65 | static struct input_handler kgdboc_reset_handler = { | ||
66 | .connect = kgdboc_reset_connect, | ||
67 | .disconnect = kgdboc_reset_disconnect, | ||
68 | .name = "kgdboc_reset", | ||
69 | .id_table = kgdboc_reset_ids, | ||
70 | }; | ||
71 | |||
72 | static DEFINE_MUTEX(kgdboc_reset_mutex); | ||
73 | |||
74 | static void kgdboc_restore_input_helper(struct work_struct *dummy) | ||
75 | { | ||
76 | /* | ||
77 | * We need to take a mutex to prevent several instances of | ||
78 | * this work running on different CPUs so they don't try | ||
79 | * to register again already registered handler. | ||
80 | */ | ||
81 | mutex_lock(&kgdboc_reset_mutex); | ||
82 | |||
83 | if (input_register_handler(&kgdboc_reset_handler) == 0) | ||
84 | input_unregister_handler(&kgdboc_reset_handler); | ||
85 | |||
86 | mutex_unlock(&kgdboc_reset_mutex); | ||
87 | } | ||
88 | |||
89 | static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper); | ||
90 | |||
91 | static void kgdboc_restore_input(void) | ||
92 | { | ||
93 | schedule_work(&kgdboc_restore_input_work); | ||
94 | } | ||
95 | |||
40 | static int kgdboc_register_kbd(char **cptr) | 96 | static int kgdboc_register_kbd(char **cptr) |
41 | { | 97 | { |
42 | if (strncmp(*cptr, "kbd", 3) == 0) { | 98 | if (strncmp(*cptr, "kbd", 3) == 0) { |
@@ -64,10 +120,12 @@ static void kgdboc_unregister_kbd(void) | |||
64 | i--; | 120 | i--; |
65 | } | 121 | } |
66 | } | 122 | } |
123 | flush_work_sync(&kgdboc_restore_input_work); | ||
67 | } | 124 | } |
68 | #else /* ! CONFIG_KDB_KEYBOARD */ | 125 | #else /* ! CONFIG_KDB_KEYBOARD */ |
69 | #define kgdboc_register_kbd(x) 0 | 126 | #define kgdboc_register_kbd(x) 0 |
70 | #define kgdboc_unregister_kbd() | 127 | #define kgdboc_unregister_kbd() |
128 | #define kgdboc_restore_input() | ||
71 | #endif /* ! CONFIG_KDB_KEYBOARD */ | 129 | #endif /* ! CONFIG_KDB_KEYBOARD */ |
72 | 130 | ||
73 | static int kgdboc_option_setup(char *opt) | 131 | static int kgdboc_option_setup(char *opt) |
@@ -231,6 +289,7 @@ static void kgdboc_post_exp_handler(void) | |||
231 | dbg_restore_graphics = 0; | 289 | dbg_restore_graphics = 0; |
232 | con_debug_leave(); | 290 | con_debug_leave(); |
233 | } | 291 | } |
292 | kgdboc_restore_input(); | ||
234 | } | 293 | } |
235 | 294 | ||
236 | static struct kgdb_io kgdboc_io_ops = { | 295 | static struct kgdb_io kgdboc_io_ops = { |