diff options
-rw-r--r-- | drivers/tty/serial/kgdboc.c | 36 | ||||
-rw-r--r-- | include/linux/kgdb.h | 7 |
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index a260cde743e2..d6ef160a40a9 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -20,6 +20,7 @@ #include <linux/vt_kern.h> #include <linux/input.h> #include <linux/module.h> +#include <linux/interrupt.h> #define MAX_CONFIG_LEN 40 @@ -304,12 +305,47 @@ static void kgdboc_post_exp_handler(void) kgdboc_restore_input(); } +static int kgdb_tty_irq; + +static int kgdboc_request_irq(irq_handler_t fn, unsigned long irqflags, + void *dev_id) +{ + int irq, res; + + /* Better to avoid double allocation in the tty driver! */ + if (kgdb_tty_irq) + return 0; + + if (!kgdb_tty_driver->ops->poll_get_irq) + return -ENODEV; + + irq = + kgdb_tty_driver->ops->poll_get_irq(kgdb_tty_driver, kgdb_tty_line); + if (irq <= 0) + return irq ? irq : -ENODEV; + + /* + * TODO: The poll_get_irq() API is bogus because we do + * not + * have any way to undo things on failure to + * request + * the IRQ. + */ + res = request_irq(irq, fn, irqflags, "kgdboc", dev_id); + if (res) + return res; + + kgdb_tty_irq = irq; + return 0; +} + static struct kgdb_io kgdboc_io_ops = { .name = "kgdboc", .read_char = kgdboc_get_char, .write_char = kgdboc_put_char, .pre_exception = kgdboc_pre_exp_handler, .post_exception = kgdboc_post_exp_handler, + .request_irq = kgdboc_request_irq, }; #ifdef CONFIG_KGDB_SERIAL_CONSOLE diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index e465bb15912d..59ecf6677f99 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -16,6 +16,7 @@ #include <linux/linkage.h> #include <linux/init.h> #include <linux/atomic.h> +#include <linux/interrupt.h> #ifdef CONFIG_HAVE_ARCH_KGDB #include <asm/kgdb.h> #endif @@ -267,6 +268,9 @@ struct kgdb_arch { * the I/O driver. * @post_exception: Pointer to a function that will do any cleanup work * for the I/O driver. + * @request_irq: Pointer to a function that can install an interrupt + * handler that will be called when a character is pending and that + * can be cleared by calling @read_char until it returns NO_POLL_CHAR. * @is_console: 1 if the end device is a console 0 if the I/O device is * not a console */ @@ -278,6 +282,9 @@ struct kgdb_io { int (*init) (void); void (*pre_exception) (void); void (*post_exception) (void); + int (*request_irq)(irq_handler_t thread_fn, + unsigned long irqflags, + void *dev_id); int is_console; }; |