From patchwork Fri Jul 17 06:20:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235671 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp1428496ilg; Thu, 16 Jul 2020 23:21:24 -0700 (PDT) X-Received: by 2002:a05:6a00:5c:: with SMTP id i28mr6898215pfk.274.1594966884170; Thu, 16 Jul 2020 23:21:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594966884; cv=none; d=google.com; s=arc-20160816; b=hglqSFujVNgJBT8tQcyKpkcd9+HjsU06JkjfmupiZfsJE113pjxudyYzYyhT9cf5Po bnQlWCW3Tuu1suYTe+TlX67eW6eie/GrfxNCEVq/C8XAjeHjleDkXo2uvq22Qzx3gGrQ l/F/oLW5xFccnR+A8ADg3Sl+CZOMkM0U5Bka7x9skeDGnJLJXwBjaQQogsAxgpDafMWe 7QIP0j7jjjfdLPM+tggGLgDP6diMQdwWEE8GVbNY9qwPEzl8p9b0WvQntwQ+wOzqISoa hngsa9pBfCSKdzoMnL3oO2D/pXTydRbx+2S6zbnSz9papMlHSmGSJ6j9WA2iR+ePzOfV /8JQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=x2rRdyrqcs5j/ENnPgmQrTRvOxeqyPVdO9GsylRc+04=; b=vbIDghURl3fDoQkwkyHlqH1e7GYJ/3byFC5nMg3BPUeDN9slax7CkA+31IAt4uRwB5 PiB8kffUGhQHQf3WgCp+3J+qdRfLFSue+P4cg6dUyP7WHklsU5IzX+V2SpEW8RVe2KHe 1s7BKDog5aWnbcT6H8suh9ysA6MsI1lJYm0CPieTtmyvario9xl+4u5UY2taUMxmP+2Y MJNS8B5eTXPkMYkrA/A1JCO7jHFBxWwvufQ5OSd5nX2VpRm5Bl+4PyZJaCmJHPu6Tpe4 N60XFtlN+opdAKoluJos+xfhp5WfGcxWHXe3US1BvJhyRsQhiBTh5hDdR48bmK+SqEP3 RYeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rJKLTvCD; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id a1sor3014746pju.31.2020.07.16.23.21.24 for (Google Transport Security); Thu, 16 Jul 2020 23:21:24 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rJKLTvCD; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=x2rRdyrqcs5j/ENnPgmQrTRvOxeqyPVdO9GsylRc+04=; b=rJKLTvCDdmifK8HKVFkzSIt0MQeJjsfM45eMogTE+80I/SM92mS/pgPXIV1fG3IJGJ HB/bJZiD1nnqdBwi0HWwV6XJc9mAUOS1yUE0lyNDZgIYPxDXCx4/h7Y1q7ZAOqqnkjkP othT8qjXcPAAGzvYTCjZQKrg0StniJtnWmThZkQ6F+jCAv1aZ+LEmbjBtnytjjKX02r6 SgReQn7fitdXbOXZy523t4FgWrWkQOHWgnduu2/2zLq8on+quxfmGCrpsEoLG2D5XfMz 1vG9Kg0lHcMenvCVFQJLuYF4ccht63/8bVH9l/T4t3YL77VBCXgWU+Vi+Qg6CwE9HlMU hBxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=x2rRdyrqcs5j/ENnPgmQrTRvOxeqyPVdO9GsylRc+04=; b=AHOS3SOv4JcCYtM76Dec40x6xkq91gm9vmqdS0cyQSr3dh/diBgVf/P9AAkIaTWm8s TBzBukINH4nORkWxn01kL6GTAx7eYki2fgMSQkDqWp8pT3ScvvvivmvPEUtnFbVE/M3H CczuhwS5V313kC5HRQ9ZFU1JMnlZ9igCYyr/e6V9e0OQmhPq4PD0ANSoHxw9l3gavr83 x0FG3FNM3+PPJqpmFsgQHR1VHbOxeQTeVbQooWFe0yH8q/QGyTFESTdbsoNxy9335w/f cjBWk3ycwwTbWj3Qikve8Tklv91zmD84rw/jviZkg2j2lbUSds05mQ8xXMG4ovoz1mjR FVaA== X-Gm-Message-State: AOAM532y809f7R67gbQUIcbrXQtWh+s5rOUfygXXOwsxCf5Tv6/aSkAt 5S54GYPi5TNeLvyd7ItuLutJf2tG X-Google-Smtp-Source: ABdhPJzMHcMN5qD/8QHauvP3wlr3VBnnKVD0HazCdg28j7wqAC/QhbUgxfJKX2i92K09dH4iCtMn9Q== X-Received: by 2002:a17:90a:3223:: with SMTP id k32mr8403144pjb.121.1594966883781; Thu, 16 Jul 2020 23:21:23 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id b4sm6630466pfo.137.2020.07.16.23.21.20 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2020 23:21:23 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v3 1/4] tty/sysrq: Make sysrq handler NMI aware Date: Fri, 17 Jul 2020 11:50:54 +0530 Message-Id: <1594966857-5215-2-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> References: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> With the advent of pseudo NMIs on arm64 it should be possible to request serial device interrupt as an NMI rather than IRQ. Having NMI driven serial RX will make it possible to do a magic sysrq in NMI context rather than in normal IRQ context. So as a preparatory step, make sysrq handler NMI aware and allow system requests to be marked as NMI safe which can run directly in NMI context while others being categorized as not NMI safe will be queued as irq_work for later processing in normal interrupt context. A particular sysrq handler is only marked as NMI safe in case the handler isn't contending for any synchronization primimitives as in NMI context they are expected to cause deadlocks. Note: Here kernel debugger (kgdb) is an exception which is a kind of stop the world debugger and designed to run in NMI context. This feature is especially helpful in case the primary CPU is stuck in deadlock with interrupts disabled and doesn't honour serial device interrupt. So having sysrq running in NMI context is helpful to debug such scenarios. Signed-off-by: Sumit Garg --- drivers/tty/sysrq.c | 33 ++++++++++++++++++++++++++++++++- include/linux/sysrq.h | 1 + kernel/debug/debug_core.c | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) -- 2.7.4 diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 7c95afa9..8017e33 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -111,6 +113,7 @@ static const struct sysrq_key_op sysrq_loglevel_op = { .help_msg = "loglevel(0-9)", .action_msg = "Changing Loglevel", .enable_mask = SYSRQ_ENABLE_LOG, + .nmi_safe = true, }; #ifdef CONFIG_VT @@ -157,6 +160,7 @@ static const struct sysrq_key_op sysrq_crash_op = { .help_msg = "crash(c)", .action_msg = "Trigger a crash", .enable_mask = SYSRQ_ENABLE_DUMP, + .nmi_safe = true, }; static void sysrq_handle_reboot(int key) @@ -170,6 +174,7 @@ static const struct sysrq_key_op sysrq_reboot_op = { .help_msg = "reboot(b)", .action_msg = "Resetting", .enable_mask = SYSRQ_ENABLE_BOOT, + .nmi_safe = true, }; const struct sysrq_key_op *__sysrq_reboot_op = &sysrq_reboot_op; @@ -217,6 +222,7 @@ static const struct sysrq_key_op sysrq_showlocks_op = { .handler = sysrq_handle_showlocks, .help_msg = "show-all-locks(d)", .action_msg = "Show Locks Held", + .nmi_safe = true, }; #else #define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL) @@ -289,6 +295,7 @@ static const struct sysrq_key_op sysrq_showregs_op = { .help_msg = "show-registers(p)", .action_msg = "Show Regs", .enable_mask = SYSRQ_ENABLE_DUMP, + .nmi_safe = true, }; static void sysrq_handle_showstate(int key) @@ -326,6 +333,7 @@ static const struct sysrq_key_op sysrq_ftrace_dump_op = { .help_msg = "dump-ftrace-buffer(z)", .action_msg = "Dump ftrace buffer", .enable_mask = SYSRQ_ENABLE_DUMP, + .nmi_safe = true, }; #else #define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL) @@ -538,6 +546,23 @@ static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p) sysrq_key_table[i] = op_p; } +#define SYSRQ_NMI_FIFO_SIZE 64 +static DEFINE_KFIFO(sysrq_nmi_fifo, int, SYSRQ_NMI_FIFO_SIZE); + +static void sysrq_do_nmi_work(struct irq_work *work) +{ + const struct sysrq_key_op *op_p; + int key; + + while (kfifo_out(&sysrq_nmi_fifo, &key, 1)) { + op_p = __sysrq_get_key_op(key); + if (op_p) + op_p->handler(key); + } +} + +static DEFINE_IRQ_WORK(sysrq_nmi_work, sysrq_do_nmi_work); + void __handle_sysrq(int key, bool check_mask) { const struct sysrq_key_op *op_p; @@ -568,7 +593,13 @@ void __handle_sysrq(int key, bool check_mask) if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { pr_info("%s\n", op_p->action_msg); console_loglevel = orig_log_level; - op_p->handler(key); + + if (in_nmi() && !op_p->nmi_safe) { + kfifo_in(&sysrq_nmi_fifo, &key, 1); + irq_work_queue(&sysrq_nmi_work); + } else { + op_p->handler(key); + } } else { pr_info("This sysrq operation is disabled.\n"); console_loglevel = orig_log_level; diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 3a582ec..630b5b9 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -34,6 +34,7 @@ struct sysrq_key_op { const char * const help_msg; const char * const action_msg; const int enable_mask; + const bool nmi_safe; }; #ifdef CONFIG_MAGIC_SYSRQ diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 9e59347..2b51173 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -943,6 +943,7 @@ static const struct sysrq_key_op sysrq_dbg_op = { .handler = sysrq_handle_dbg, .help_msg = "debug(g)", .action_msg = "DEBUG", + .nmi_safe = true, }; #endif From patchwork Fri Jul 17 06:20:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235672 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp1428546ilg; Thu, 16 Jul 2020 23:21:29 -0700 (PDT) X-Received: by 2002:a65:6707:: with SMTP id u7mr7376299pgf.233.1594966889152; Thu, 16 Jul 2020 23:21:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594966889; cv=none; d=google.com; s=arc-20160816; b=J5cAwY6k8MTbzFj4sZuQhCDtcdMhP6O+v3ORuYgcj6YXmf17D/vIfl4H5PfGSYsCyc KKCjBphvyy9rNO8hf5kIGnfQaONzv7cQtvSEAI7Mh8Ljn81i0sJ+TmBmSUAFDF9T3AhQ iu6n+Ltrn2MDcfQyV2jaW/PoJkezH3g9J0N16kNc3+LB9Wm/Wm/p4CJAgpW6A40+d3Ky 8nDUxSt+UKuwAHMRL7kgq9Pi98FbNxsmDKw/q+3FHnCP/T2xHkzebYRK0wN7bmfm+QIF Zd0srBmMoRFQ3MOLK5PKuGevOi+Yh2tKYl+zG/7i7ukaj+mtkz9cE7pebU9Ox4zsLpfz fk2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=d9jgaYzqa/Xp8bfEMe71U9w/oiR/y7kdym77YvEoKHo=; b=AOdwrT3ikeVGlYUXVGO94rqKE1VHKd+AKab7N+IGZ6NS/NKMN+4dHg4+13ISLl7YRs Abj50rBZJlosDn3STaSafEwZ50LbsDi700cPwjhBZ0/oVby8VTnWYK5TdExNTFqFs/O5 Yi+pTotd5jDe4tpT1WoMxV5vWniJL3X5WVjoS1KX2JQ+7s1rvQ3FDuephDwrvDe4H3eP mS9V/paHi++4WtZHTUGzvnPF98XnqGxbNzNAx+qKoKnFy/9T8iQd6WFzbY8XS9ZG/47A flta51xQm7eJilUe5fYj5oyodwEShJO7xxuIEG8cqUrnKyhg8dM0witWLmQPQhq5lUIl hL7w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JNO0JHXM; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id d8sor2951416pja.43.2020.07.16.23.21.29 for (Google Transport Security); Thu, 16 Jul 2020 23:21:29 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JNO0JHXM; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=d9jgaYzqa/Xp8bfEMe71U9w/oiR/y7kdym77YvEoKHo=; b=JNO0JHXMzQUF26hyna70dkSKOh5zg4GLKb1HKvb1vuUjK12XuKk8uoLOqTRGJPcz5F 0skIvwKO1aFBlfPvBl8e5Itbm/3ci6YeQFGbJ9/7Cd0iXHeICt9NuNxQeoboDWQSOmHj 6eXnUfw/03P+jNmlxS87WgSDcevzwUVoAm9jFjavFW+QrO9l5Gwdk4dd4eqr4X3H2psu uXHz66HDLr8aZ9Ig2dUx6GC4Vtq6gDJbjMf+hHviUcgEXHoNKo/tnX7j714WgoNY436k lyW/MrNiijuVow/yzwOs6NzSUI/21g2GsLiSs+FAhXC2dq9WV72HtfANI+lsfFs4fdDk V1aA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d9jgaYzqa/Xp8bfEMe71U9w/oiR/y7kdym77YvEoKHo=; b=THPC3XMjqd6qv6wpBDb6+BK7iEFWSwaOqxxTUrHCSlc5rIJxfag4+vFQDQXbN4T44U MEEz+Z072BYhKReN0Db3tIBnsUGtvOrSYtdetJZmBSOfPDWIZuhEQr0o3I02hKqB7tUE PhAKrA7rRV2L6jFY1IRqOwu6vuVCY0PwpCBnrTMTmpHzNBxJlvHkPIWvbaj9z028Wcik GPkNB/f/M2SkE3Icv4yrbNPuLu+dvlLGyegeRK1R3HhxogBTapppujR1/tdpnXOBvzZu czYsDOcSKjo4N7RFxtW2k6j2iVFpxUC2sHpF5Ikx+Y8suLrKbbuz6xDATedx7scMHc1C PJaQ== X-Gm-Message-State: AOAM531OviaTSrS/VMYmv7t2OzhW6j7gFymQk4xMugsLzm23A4bWNObl txhV/TUTC2XiJvm3YdH5xJ8jzCCJThEIWg== X-Google-Smtp-Source: ABdhPJwgadiOK6bOJRPuD8vtA8CQ7/hWDPW3/09tvBkAWqmAUCkAn5ylwTRy3eFaCac8uLqc7DWqtQ== X-Received: by 2002:a17:90a:d314:: with SMTP id p20mr7581654pju.99.1594966888688; Thu, 16 Jul 2020 23:21:28 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id b4sm6630466pfo.137.2020.07.16.23.21.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2020 23:21:27 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v3 2/4] serial: core: Add framework to allow NMI aware serial drivers Date: Fri, 17 Jul 2020 11:50:55 +0530 Message-Id: <1594966857-5215-3-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> References: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> With the advent of pseudo NMIs on arm64 platforms, it will be possible to have NMI driven serial drivers which enables us to have magic sysrq running in NMI context. So add NMI framework APIs in serial core that can be leveraged by serial drivers operating in polling mode to have NMI driven serial transfers. The general idea is to intercept RX characters in NMI context, if those are specific to magic sysrq then allow corresponding handler to run in NMI context. Otherwise defer all NMI unsafe RX and TX operations to IRQ work queue in order to run those in normal interrupt context. Also, since magic sysrq entry APIs can be invoked from NMI context, so make those APIs NMI safe via deferring NMI unsafe work to IRQ work queue. Signed-off-by: Sumit Garg --- drivers/tty/serial/serial_core.c | 120 ++++++++++++++++++++++++++++++++++++++- include/linux/serial_core.h | 67 ++++++++++++++++++++++ 2 files changed, 185 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 57840cf..6342e90 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3181,8 +3181,14 @@ static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) return true; } +#ifdef CONFIG_CONSOLE_POLL + if (in_nmi()) + irq_work_queue(&port->nmi_state.sysrq_toggle_work); + else + schedule_work(&sysrq_enable_work); +#else schedule_work(&sysrq_enable_work); - +#endif port->sysrq = 0; return true; } @@ -3273,12 +3279,122 @@ int uart_handle_break(struct uart_port *port) port->sysrq = 0; } - if (port->flags & UPF_SAK) + if (port->flags & UPF_SAK) { +#ifdef CONFIG_CONSOLE_POLL + if (in_nmi()) + irq_work_queue(&port->nmi_state.sysrq_sak_work); + else + do_SAK(state->port.tty); +#else do_SAK(state->port.tty); +#endif + } return 0; } EXPORT_SYMBOL_GPL(uart_handle_break); +#ifdef CONFIG_CONSOLE_POLL +int uart_nmi_handle_char(struct uart_port *port, unsigned int status, + unsigned int overrun, unsigned int ch, + unsigned int flag) +{ + struct uart_nmi_rx_data rx_data; + + if (!in_nmi()) + return 0; + + rx_data.status = status; + rx_data.overrun = overrun; + rx_data.ch = ch; + rx_data.flag = flag; + + if (!kfifo_in(&port->nmi_state.rx_fifo, &rx_data, 1)) + ++port->icount.buf_overrun; + + return 1; +} +EXPORT_SYMBOL_GPL(uart_nmi_handle_char); + +static void uart_nmi_rx_work(struct irq_work *rx_work) +{ + struct uart_nmi_state *nmi_state = + container_of(rx_work, struct uart_nmi_state, rx_work); + struct uart_port *port = + container_of(nmi_state, struct uart_port, nmi_state); + struct uart_nmi_rx_data rx_data; + + /* + * In polling mode, serial device is initialized much prior to + * TTY port becoming active. This scenario is especially useful + * from debugging perspective such that magic sysrq or debugger + * entry would still be possible even when TTY port isn't + * active (consider a boot hang case or if a user hasn't opened + * the serial port). So we discard any other RX data apart from + * magic sysrq commands in case TTY port isn't active. + */ + if (!port->state || !tty_port_active(&port->state->port)) { + kfifo_reset(&nmi_state->rx_fifo); + return; + } + + spin_lock(&port->lock); + while (kfifo_out(&nmi_state->rx_fifo, &rx_data, 1)) + uart_insert_char(port, rx_data.status, rx_data.overrun, + rx_data.ch, rx_data.flag); + spin_unlock(&port->lock); + + tty_flip_buffer_push(&port->state->port); +} + +static void uart_nmi_tx_work(struct irq_work *tx_work) +{ + struct uart_nmi_state *nmi_state = + container_of(tx_work, struct uart_nmi_state, tx_work); + struct uart_port *port = + container_of(nmi_state, struct uart_port, nmi_state); + + spin_lock(&port->lock); + if (nmi_state->tx_irq_callback) + nmi_state->tx_irq_callback(port); + spin_unlock(&port->lock); +} + +static void uart_nmi_sak_work(struct irq_work *work) +{ + struct uart_nmi_state *nmi_state = + container_of(work, struct uart_nmi_state, sysrq_sak_work); + struct uart_port *port = + container_of(nmi_state, struct uart_port, nmi_state); + + do_SAK(port->state->port.tty); +} + +#ifdef CONFIG_MAGIC_SYSRQ_SERIAL +static void uart_nmi_toggle_work(struct irq_work *work) +{ + schedule_work(&sysrq_enable_work); +} +#endif + +int uart_nmi_state_init(struct uart_port *port) +{ + int ret; + + ret = kfifo_alloc(&port->nmi_state.rx_fifo, 256, GFP_KERNEL); + if (ret) + return ret; + + init_irq_work(&port->nmi_state.rx_work, uart_nmi_rx_work); + init_irq_work(&port->nmi_state.tx_work, uart_nmi_tx_work); + init_irq_work(&port->nmi_state.sysrq_sak_work, uart_nmi_sak_work); +#ifdef CONFIG_MAGIC_SYSRQ_SERIAL + init_irq_work(&port->nmi_state.sysrq_toggle_work, uart_nmi_toggle_work); +#endif + return ret; +} +EXPORT_SYMBOL_GPL(uart_nmi_state_init); +#endif + EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9fd550e..84487a9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #ifdef CONFIG_SERIAL_CORE_CONSOLE @@ -103,6 +105,28 @@ struct uart_icount { typedef unsigned int __bitwise upf_t; typedef unsigned int __bitwise upstat_t; +#ifdef CONFIG_CONSOLE_POLL +struct uart_nmi_rx_data { + unsigned int status; + unsigned int overrun; + unsigned int ch; + unsigned int flag; +}; + +struct uart_nmi_state { + bool active; + + struct irq_work tx_work; + void (*tx_irq_callback)(struct uart_port *port); + + struct irq_work rx_work; + DECLARE_KFIFO_PTR(rx_fifo, struct uart_nmi_rx_data); + + struct irq_work sysrq_sak_work; + struct irq_work sysrq_toggle_work; +}; +#endif + struct uart_port { spinlock_t lock; /* port lock */ unsigned long iobase; /* in/out[bwl] */ @@ -255,6 +279,9 @@ struct uart_port { struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */ struct serial_iso7816 iso7816; void *private_data; /* generic platform data pointer */ +#ifdef CONFIG_CONSOLE_POLL + struct uart_nmi_state nmi_state; +#endif }; static inline int serial_port_in(struct uart_port *up, int offset) @@ -475,4 +502,44 @@ extern int uart_handle_break(struct uart_port *port); !((cflag) & CLOCAL)) int uart_get_rs485_mode(struct uart_port *port); + +/* + * The following are helper functions for the NMI aware serial drivers. + * Currently NMI support is only enabled under polling mode. + */ + +#ifdef CONFIG_CONSOLE_POLL +int uart_nmi_state_init(struct uart_port *port); +int uart_nmi_handle_char(struct uart_port *port, unsigned int status, + unsigned int overrun, unsigned int ch, + unsigned int flag); + +static inline bool uart_nmi_active(struct uart_port *port) +{ + return port->nmi_state.active; +} + +static inline void uart_set_nmi_active(struct uart_port *port, bool val) +{ + port->nmi_state.active = val; +} +#else +static inline int uart_nmi_handle_char(struct uart_port *port, + unsigned int status, + unsigned int overrun, + unsigned int ch, unsigned int flag) +{ + return 0; +} + +static inline bool uart_nmi_active(struct uart_port *port) +{ + return false; +} + +static inline void uart_set_nmi_active(struct uart_port *port, bool val) +{ +} +#endif + #endif /* LINUX_SERIAL_CORE_H */ From patchwork Fri Jul 17 06:20:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235673 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp1428574ilg; Thu, 16 Jul 2020 23:21:32 -0700 (PDT) X-Received: by 2002:aa7:952b:: with SMTP id c11mr6454712pfp.186.1594966892689; Thu, 16 Jul 2020 23:21:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594966892; cv=none; d=google.com; s=arc-20160816; b=vMNDdsoUruNKY3htNsuZae8FLJ+3VXgl1JSYpvQMPigqYIcbpvuJA7WOKpk6A9y8A/ /xXIFG/NJ3pkuMbPntHSA6FtDb5cOKsTyzokYV/ph/TccE0SCTj4ZjafUE2hVR5+Ndt9 WkZrnvCAzzrGnLdhdP9u3Rhp7i+OGtMU07CktfpsPuhUNu9FdZsS4m83to+6FyEnMchF /2u2BWx6rVo/eA9LGYC0pWurcAmgqYEQryXzdr9njJGLv8DOkmtZJzbOw2+Spq8l+REx Fu6nS7fjcF8Yk1EuPua5koDBeuIWpP5cpEgKX1pqDXubXzl2/yCjhkPD19YXdJuoU2jY HHYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=L5QBpzbQ08BmWVXWQQ1Ei99UM9wMUTbD0qwaSmoJOcI=; b=0rQvPaARb+gg4bb/6W5ulboruXdFloLZpL8vYMLN4gNCo45PTE6DfGyFCutCa9wu/3 t1YB/jHhXFdc2/2h3DT9Jrl+niZcBIs0VBu4FdLjhk5f0OaAPZ07JuWMdK0u9lv9Xu04 cHZHV/vBVEs9TKFIZUV+T+mhLwj9ydPbQs0QCz3P43AkrFMqeEy3X35fHgbkfKlGJpfH vmVgW/1DwZc6ywbEJDLs9jqhjq35TdMpGUbYc9A+BLJfteghQo4S5tK1iGQ+KZQCs7NB OWVWqLtogD2RNxVyx+DBQKNcJmq5y3XK727waggw6DAlbAKsy7wnmLino7zLjAX0/ndD eKDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gTC7pGqe; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id u187sor9529168pfc.23.2020.07.16.23.21.32 for (Google Transport Security); Thu, 16 Jul 2020 23:21:32 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gTC7pGqe; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=L5QBpzbQ08BmWVXWQQ1Ei99UM9wMUTbD0qwaSmoJOcI=; b=gTC7pGqexKEtOt/EEe5nAmuhbNNrpxIivm+6PfiC7zsLJ7gWwvyjPmjs7iLibIwl3T nGxrIenzEXgxrzMI3b7fLfvpwM4akS7HU14lj+D3i9TTKncBPEjf7S6WIk79ea2zDrcs xa17j/4QC3oozBgUU6inzXPqtkIs7kN8GI3le3xqJKqKTmD+DThySzae9dsUX4Z8oJcQ xPj7E2ccd7yk+LRFJhyM7v3Us5NaSOhDP14RM/4rtDvNDRAvhjXUUANPf1rS2vc2Rg9m ewixmrB6dqLnMDYE6nFJX7BWMSJoc210IfrzL4dLJ/z0n+GTOt8mmpazqTQmjUpcHBJu TdtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=L5QBpzbQ08BmWVXWQQ1Ei99UM9wMUTbD0qwaSmoJOcI=; b=Jh2uN3xYReHFR5QLwuGJs9X69imJdPy3K2393RMv5r7EKXtvbsx1RmE6c08C1P12WB hcZlTDX0Lz6GyErOV6Gfbl93QLmB+zDL7Sqy8HnOGkGjXDY7coice0bh4NoQbG6+uxgU oJbC2qSq2V4DuExoSdOBy5Y18mX8kqel+NKT5GOGwvLWkjgQUV67b0JXbRN+WMglLBpr RgvQM40tfG02GrpygIW+KSocoI40mZcra8tp+JUhJ/BH2PME5jHngIudDDg3bfzjzTpk YrxIGiRzv7O3LIFnhEzOfKrE7GfSLFSXzI4v+nAyKA/5UzdLtV6rbMw1KWMShEOINhuQ YBcQ== X-Gm-Message-State: AOAM532swlsGyE/fc+m6fJGRXO2adFCt+rIyV6FX2YxsvpCKeCdWDr6R SeEyGh9ccHMyXWdnbsNVrxTSpsh0B8vn7Q== X-Google-Smtp-Source: ABdhPJxG7sl50KcDKc9bA7QScxvgGLQCM+m84k0PqpBCOIaAdsu6y4LI6J/BGnqoXKCGCL977I3MSA== X-Received: by 2002:aa7:9419:: with SMTP id x25mr6855850pfo.67.1594966892217; Thu, 16 Jul 2020 23:21:32 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id b4sm6630466pfo.137.2020.07.16.23.21.29 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2020 23:21:31 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v3 3/4] serial: amba-pl011: Re-order APIs definition Date: Fri, 17 Jul 2020 11:50:56 +0530 Message-Id: <1594966857-5215-4-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> References: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> Re-order pl011_hwinit() and pl011_enable_interrupts() APIs definition to allow their re-use in polling mode. Signed-off-by: Sumit Garg --- drivers/tty/serial/amba-pl011.c | 148 ++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 74 deletions(-) -- 2.7.4 diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8efd7c2..0983c5e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1581,6 +1581,80 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&uap->port.lock, flags); } +static int pl011_hwinit(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + int retval; + + /* Optionaly enable pins to be muxed in and configured */ + pinctrl_pm_select_default_state(port->dev); + + /* + * Try to enable the clock producer. + */ + retval = clk_prepare_enable(uap->clk); + if (retval) + return retval; + + uap->port.uartclk = clk_get_rate(uap->clk); + + /* Clear pending error and receive interrupts */ + pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | + UART011_FEIS | UART011_RTIS | UART011_RXIS, + uap, REG_ICR); + + /* + * Save interrupts enable mask, and enable RX interrupts in case if + * the interrupt is used for NMI entry. + */ + uap->im = pl011_read(uap, REG_IMSC); + pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); + + if (dev_get_platdata(uap->port.dev)) { + struct amba_pl011_data *plat; + + plat = dev_get_platdata(uap->port.dev); + if (plat->init) + plat->init(); + } + return 0; +} + +/* + * Enable interrupts, only timeouts when using DMA + * if initial RX DMA job failed, start in interrupt mode + * as well. + */ +static void pl011_enable_interrupts(struct uart_amba_port *uap) +{ + unsigned int i; + + spin_lock_irq(&uap->port.lock); + + /* Clear out any spuriously appearing RX interrupts */ + pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); + + /* + * RXIS is asserted only when the RX FIFO transitions from below + * to above the trigger threshold. If the RX FIFO is already + * full to the threshold this can't happen and RXIS will now be + * stuck off. Drain the RX FIFO explicitly to fix this: + */ + for (i = 0; i < uap->fifosize * 2; ++i) { + if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE) + break; + + pl011_read(uap, REG_DR); + } + + uap->im = UART011_RTIM; + if (!pl011_dma_rx_running(uap)) + uap->im |= UART011_RXIM; + pl011_write(uap->im, uap, REG_IMSC); + spin_unlock_irq(&uap->port.lock); +} + #ifdef CONFIG_CONSOLE_POLL static void pl011_quiesce_irqs(struct uart_port *port) @@ -1639,46 +1713,6 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_hwinit(struct uart_port *port) -{ - struct uart_amba_port *uap = - container_of(port, struct uart_amba_port, port); - int retval; - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(port->dev); - - /* - * Try to enable the clock producer. - */ - retval = clk_prepare_enable(uap->clk); - if (retval) - return retval; - - uap->port.uartclk = clk_get_rate(uap->clk); - - /* Clear pending error and receive interrupts */ - pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | - UART011_FEIS | UART011_RTIS | UART011_RXIS, - uap, REG_ICR); - - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = pl011_read(uap, REG_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); - - if (dev_get_platdata(uap->port.dev)) { - struct amba_pl011_data *plat; - - plat = dev_get_platdata(uap->port.dev); - if (plat->init) - plat->init(); - } - return 0; -} - static bool pl011_split_lcrh(const struct uart_amba_port *uap) { return pl011_reg_to_offset(uap, REG_LCRH_RX) != @@ -1707,40 +1741,6 @@ static int pl011_allocate_irq(struct uart_amba_port *uap) return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); } -/* - * Enable interrupts, only timeouts when using DMA - * if initial RX DMA job failed, start in interrupt mode - * as well. - */ -static void pl011_enable_interrupts(struct uart_amba_port *uap) -{ - unsigned int i; - - spin_lock_irq(&uap->port.lock); - - /* Clear out any spuriously appearing RX interrupts */ - pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); - - /* - * RXIS is asserted only when the RX FIFO transitions from below - * to above the trigger threshold. If the RX FIFO is already - * full to the threshold this can't happen and RXIS will now be - * stuck off. Drain the RX FIFO explicitly to fix this: - */ - for (i = 0; i < uap->fifosize * 2; ++i) { - if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE) - break; - - pl011_read(uap, REG_DR); - } - - uap->im = UART011_RTIM; - if (!pl011_dma_rx_running(uap)) - uap->im |= UART011_RXIM; - pl011_write(uap->im, uap, REG_IMSC); - spin_unlock_irq(&uap->port.lock); -} - static int pl011_startup(struct uart_port *port) { struct uart_amba_port *uap = From patchwork Fri Jul 17 06:20:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235674 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp1428602ilg; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) X-Received: by 2002:a65:4b85:: with SMTP id t5mr7363590pgq.36.1594966895797; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594966895; cv=none; d=google.com; s=arc-20160816; b=pILALJcLFmBfLYrLXeFq4VWcX0a8WCfWkS00Qg7JWhAZDnv01VV61Gf7Gf0Yywl0Rc b4DGtn3aRxLFeHhU20KMHPDDTZ3WVOdH0OiMDvvH8dWDvQT2j0GEi5+34BMa6SGivD3g +nkt7pFQrpuREM9MIw/W7qPdm2ZdluEv1iSTzxB6RfI8W7lhXgZYn8cePzOOaQmCtCip 2ayefARcFbJDx8xWY54acNQGe1iMaiizFeBj5LUstrPC+eg7lTcfoM/iCJQD+NkFLvBi MN70WYfS5nEil+GCy+N78ttckp0eNeOpYxEa4MlBXVx9YeSMbcQzh1IdYKdavXCs8vwQ qOhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=DySdNE3Or4siCJOigOPu7wC57fOagP27AEQTL9InHV+HcKNZ6ErNRrxnld3QAqhvJe rdycEreGrXJkWv4XtMeIfp01bwxaqJRCiUeDMthCYv6yLrzCDTGe5JOnev+tqwnPKfOq R0Xl9vBQpP+oZqAR8/TR8s+670if5oABHIPvAOdM+ftytj0F4AigV9Jqdcu7dks5AMkv AKpD98jVqjWIiOXhXrBc9WE8Z1L0HOVzh9FWUmEnnUBbCtZoodTE0ZDGoXNdB7yuQPDS +shxvuLq98yA2L7ZxhwYWe2LUykYQF5Obh3m8p1m8iejKhMmzvub4FUK3f4SqEw6QvTU VoQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="hp3zE/K9"; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id d4sor9636382plo.37.2020.07.16.23.21.35 for (Google Transport Security); Thu, 16 Jul 2020 23:21:35 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="hp3zE/K9"; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=hp3zE/K9KZCG3FwVVl6SX8IDDdmE2zyQ5P7u3iq3sr0/f7V7X2twK9cM5dVt8r6h4F 4edybJoEzWXUNTaAEsZcHM2w9HBy8wQh2QhaLrwoQqLd2LWqCYwgR/xVdqUvVycsCfHs ECpwkwDF1ZeYiCkB6XGKIm2buF6eDLTLjze97NCXdZb7a1d9xFTTboh9dVz+L806ioOv ox7gCDSjtAlI0y9EaWp9mBFPWl2IVhlYbwZ8OJzI4Yfgetcn4mZQWCeix6tdKRWeXWRI KYSbbTSyHTDDRGriEcENrvLW6gfqdRhYamZYnaPK4pLycOZNFuUKJSJGbdC2Pk3juIan H6Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=mqLQHaPwFeTs0Ybs53ogA2u6wT9Nisz+CxFmj7hIQBWqizKDnpfIfmiRB8x8GZSSEG 0lW8Adn1sBcqFCK9RKig2la+kPnqSVRv06NULflyAcvKOJK8e69yPcqkJ7z1JwF5/aZk XOxX5Nq7CTIOlV5GywLrRX4EpJJ+z944ONIrXF40uhKh7aQc5a7fU7xuZv4ff8XmRc8f L/mivx7uN8juoQZmtWJwwZAZZh+u6XP4Q4+0OiE1F4Lh9wNFRp0eLq76k8nvebDzjW5W p3lgiJ73GdREb8V8jOD3ZLYQ3ObUd4y9ZQ0WjJF2TEw4zX0Jggguj+a56XGD9ZMsAkl8 OQOw== X-Gm-Message-State: AOAM531WUoShODCLYVgXoW1weA38Qx8dIvaRn0ZYraNpF0X3DMOB3/T1 JIIRuG2bvllXXyqKvtEBY0JpE5ROPGtSGQ== X-Google-Smtp-Source: ABdhPJxJSEY3JpYapPyJgRFfb6CcKqkYiNmE8ZVIUlkh0Y3kcaCulBxV1MAVNYwO8FmVlhRD8liyUA== X-Received: by 2002:a17:902:9a4b:: with SMTP id x11mr6512647plv.255.1594966895386; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id b4sm6630466pfo.137.2020.07.16.23.21.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2020 23:21:34 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v3 4/4] serial: amba-pl011: Enable NMI aware polling mode Date: Fri, 17 Jul 2020 11:50:57 +0530 Message-Id: <1594966857-5215-5-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> References: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> Allow serial interrupt to be requested as an NMI in polling mode. Currently this NMI aware polling mode only supports NMI driven RX and TX data. DMA operation isn't supported. Also, while operating in NMI mode, RX always remains active irrespective of whether corresponding TTY port is active or not. So we directly bail out of startup, shutdown and rx_stop APIs if NMI mode is active. Signed-off-by: Sumit Garg --- drivers/tty/serial/amba-pl011.c | 128 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0983c5e..36c32b8 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "amba-pl011.h" @@ -347,6 +349,10 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) if (uart_handle_sysrq_char(&uap->port, ch & 255)) continue; + if (uart_nmi_handle_char(&uap->port, ch, UART011_DR_OE, ch, + flag)) + continue; + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); } @@ -1316,6 +1322,9 @@ static void pl011_stop_rx(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); pl011_write(uap->im, uap, REG_IMSC); @@ -1604,13 +1613,6 @@ static int pl011_hwinit(struct uart_port *port) UART011_FEIS | UART011_RTIS | UART011_RXIS, uap, REG_ICR); - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = pl011_read(uap, REG_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); - if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1711,6 +1713,100 @@ static void pl011_put_poll_char(struct uart_port *port, pl011_write(ch, uap, REG_DR); } +static void pl011_nmi_rx_chars(struct uart_amba_port *uap) +{ + pl011_fifo_to_tty(uap); + irq_work_queue(&uap->port.nmi_state.rx_work); +} + +static irqreturn_t pl011_nmi_int(int irq, void *dev_id) +{ + struct uart_amba_port *uap = dev_id; + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + int handled = 0; + + status = pl011_read(uap, REG_MIS); + if (status) { + do { + check_apply_cts_event_workaround(uap); + + pl011_write(status, uap, REG_ICR); + + if (status & (UART011_RTIS|UART011_RXIS)) + pl011_nmi_rx_chars(uap); + + if (status & UART011_TXIS) + irq_work_queue(&uap->port.nmi_state.tx_work); + + if (pass_counter-- == 0) + break; + + status = pl011_read(uap, REG_MIS); + } while (status != 0); + handled = 1; + } + + return IRQ_RETVAL(handled); +} + +static int pl011_allocate_nmi(struct uart_amba_port *uap) +{ + int ret; + + irq_set_status_flags(uap->port.irq, IRQ_NOAUTOEN); + ret = request_nmi(uap->port.irq, pl011_nmi_int, IRQF_PERCPU, + "uart-pl011", uap); + if (ret) { + irq_clear_status_flags(uap->port.irq, IRQ_NOAUTOEN); + return ret; + } + + enable_irq(uap->port.irq); + + return ret; +} + +static void pl011_tx_irq_callback(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + + spin_lock(&port->lock); + pl011_tx_chars(uap, true); + spin_unlock(&port->lock); +} + +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + int retval; + + retval = pl011_hwinit(port); + if (retval) + goto clk_dis; + + /* In case NMI isn't supported, fallback to normal interrupt mode */ + retval = pl011_allocate_nmi(uap); + if (retval) + return 0; + + retval = uart_nmi_state_init(port); + if (retval) + goto clk_dis; + + port->nmi_state.tx_irq_callback = pl011_tx_irq_callback; + uart_set_nmi_active(port, true); + + pl011_enable_interrupts(uap); + + return 0; + + clk_dis: + clk_disable_unprepare(uap->clk); + return retval; +} + #endif /* CONFIG_CONSOLE_POLL */ static bool pl011_split_lcrh(const struct uart_amba_port *uap) @@ -1736,8 +1832,6 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_write(uap->im, uap, REG_IMSC); - return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); } @@ -1748,6 +1842,9 @@ static int pl011_startup(struct uart_port *port) unsigned int cr; int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) goto clk_dis; @@ -1790,6 +1887,9 @@ static int sbsa_uart_startup(struct uart_port *port) container_of(port, struct uart_amba_port, port); int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) return retval; @@ -1859,6 +1959,9 @@ static void pl011_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); pl011_dma_shutdown(uap); @@ -1891,6 +1994,9 @@ static void sbsa_uart_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); free_irq(uap->port.irq, uap); @@ -2142,7 +2248,7 @@ static const struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2173,7 +2279,7 @@ static const struct uart_ops sbsa_uart_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif