aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2018-01-01 13:04:37 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2018-01-01 13:04:37 +0000
commitf1005945c613077fe682e55396a4a8c1d32c784b (patch)
treee39eae69ebb00dc9c37b45c6ec4ca7e093e9375a
parent9a384e838082553e0d0ba04f4b3fd2d9876ae9e9 (diff)
downloadlinux-f1005945c613077fe682e55396a4a8c1d32c784b.tar.gz
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.c47
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)