diff options
author | Daniel Thompson <daniel.thompson@linaro.org> | 2018-01-01 13:04:37 +0000 |
---|---|---|
committer | Daniel Thompson <daniel.thompson@linaro.org> | 2018-01-01 13:04:37 +0000 |
commit | f1005945c613077fe682e55396a4a8c1d32c784b (patch) | |
tree | e39eae69ebb00dc9c37b45c6ec4ca7e093e9375a | |
parent | 9a384e838082553e0d0ba04f4b3fd2d9876ae9e9 (diff) |
serial: kgdb_nmi: Add support for interrupt based fallback
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
-rw-r--r-- | drivers/tty/serial/kgdb_nmi.c | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index 117df151627d..195b1fad2ff9 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c @@ -44,9 +44,46 @@ MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)"); static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0); +static int kgdb_nmi_poll_one_knock(void); + +static irqreturn_t kgdb_nmi_handle_irq(int irq, void *dev_id) +{ + int ret; + + if (kgdb_nmi_knock < 0) { + kgdb_breakpoint(); + return IRQ_HANDLED; + } + + ret = kgdb_nmi_poll_one_knock(); + if (ret == NO_POLL_CHAR) + return IRQ_NONE; + + while (ret != 1) { + ret = kgdb_nmi_poll_one_knock(); + if (ret == NO_POLL_CHAR) + return IRQ_HANDLED; + } + + kgdb_breakpoint(); + return IRQ_HANDLED; +} + static int kgdb_nmi_console_setup(struct console *co, char *options) { - arch_kgdb_ops.enable_nmi(1); + int res; + + if (arch_kgdb_ops.enable_nmi) { + arch_kgdb_ops.enable_nmi(1); + } else if (dbg_io_ops->request_irq) { + res = dbg_io_ops->request_irq(kgdb_nmi_handle_irq, 0, NULL); + if (res) { + pr_err("ttyNMI0: Cannot request irq\n"); + return res; + } + } else { + return -ENODEV; + } /* The NMI console uses the dbg_io_ops to issue console messages. To * avoid duplicate messages during kdb sessions we must inform kdb's @@ -330,9 +367,6 @@ int kgdb_register_nmi_console(void) { int ret; - if (!arch_kgdb_ops.enable_nmi) - return 0; - kgdb_nmi_tty_driver = alloc_tty_driver(1); if (!kgdb_nmi_tty_driver) { pr_err("%s: cannot allocate tty\n", __func__); @@ -368,9 +402,8 @@ int kgdb_unregister_nmi_console(void) { int ret; - if (!arch_kgdb_ops.enable_nmi) - return 0; - arch_kgdb_ops.enable_nmi(0); + if (arch_kgdb_ops.enable_nmi) + arch_kgdb_ops.enable_nmi(0); ret = unregister_console(&kgdb_nmi_console); if (ret) |