From patchwork Tue Jul 21 12:10:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11675585 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E64214E3 for ; Tue, 21 Jul 2020 12:12:49 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 68724206E9 for ; Tue, 21 Jul 2020 12:12:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="H24GBDTl"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="qCxiWVCI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 68724206E9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=v4bUSKCPmZOEnCwRcvi6AJqwTjnueDPxY6nzMFFlvzs=; b=H24GBDTleb0PJjQjjqMT/IP7Gk 9VuD2j5DOJw5SzoPXbkCRrzyoarkMKh1ahDgJaynWVk3YFakznQihSZ+GKwS18uaGEJVFnt/DIbuq 7BopVtdCXLFx+k7PV9PglH29PJNNx9Ojq+lhK75jF/wDDsRzHg7jkXBJFYKQB66yNl9Ob2GpbG5ME JbAJG9HZUw933A37hHLlMAgN0cd3k7tge+HGFxT7ohBNnjQvrc2zBs4Y/SWcyOz4+4sVY+8T505pV Pn0eZbL8GTisfTSRhcP4r+1f/bMpD1n/L9Iu8m3sKYimzjMpZ5V377NvS3uQuspEDFJyaVUIbc78k WMiTe68w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jxr7D-0000S6-3g; Tue, 21 Jul 2020 12:11:23 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jxr73-0000Ns-GW for linux-arm-kernel@lists.infradead.org; Tue, 21 Jul 2020 12:11:14 +0000 Received: by mail-pg1-x541.google.com with SMTP id j19so11835052pgm.11 for ; Tue, 21 Jul 2020 05:11:12 -0700 (PDT) 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=2zOkNlooR1zcsl5ai3d/r17122nHEKv/dFvwHU/KZrA=; b=qCxiWVCIYBZyxLsMeE0w7kCkNJoBZ7QRMGqB8iz9+cZylR3Kxiuii46cbejMIY5/Np ZPzpH/PyZvdzSoaoO7jzVg7fQcXnSQx4/lfSr/0aek5vJ/moI57rKq5+4cqL+06Q6siA ziJkw20K+BOosurBJ8w5GtJj6skjC3rNixycBb+zVpuP1yXWrvoEsRM3SArliy201rSc Kmlz87fkvx+pqm6TXR7sILSVPWtN5AMhcvfyLkpHxVnnib/39NDu7LBfAoHjxHNspceS kmhG+kH5t7cmNe14hfKOHg7LeuJT4Q0m0CwyhqWLQqnc3T6DfETzD4UG11CpF2kCND1/ Dc5w== 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=2zOkNlooR1zcsl5ai3d/r17122nHEKv/dFvwHU/KZrA=; b=nmSUsSWtDUUDReNACCQIb6X3n1FAzeRsEyOb9IrFdObDXUXUZrimcPjupszB11TDHz 4qbjmuvAa5ttk9T/0rkC4FOgK6kkZ2bj5kuMlAK9I+XKoTNxWSvJcSLL2XyshXgRisJ2 JQbsOHUUo39pGpp0SYLezy0d/PGkv974rjTBaZvyAXm+jmxaoDofSmT8/0tBhXKT97wG X9LUgq3t7SYNdln8qn3bN1cMwmhmKA9/9f+xO2/GXaMdpiZPdO5A5dxCQAAap8V8aqL7 NZ6kzuFnn+lgcgRi5R/sXoCFxhm12Ope27XSshwKzFYD2gG6Hu4Zv7EHfd3TkO93iRuV AiGg== X-Gm-Message-State: AOAM533bqQbbc/7zbVrhKWVuYTAK16vtB+IH0SGoLJEUtzQFd3ZCEElM arqcll5tKGyrYJiufXnfJypatg== X-Google-Smtp-Source: ABdhPJwKUmsn6lRMXYTYzTogmHp0PD64aIq6+1XW2ha8ClQcPj9F4Yp1/qWxe7LuhU7j6OSsyTNzkg== X-Received: by 2002:a05:6a00:2292:: with SMTP id f18mr24239679pfe.192.1595333471193; Tue, 21 Jul 2020 05:11:11 -0700 (PDT) Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id w9sm20601992pfq.178.2020.07.21.05.11.05 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Jul 2020 05:11:10 -0700 (PDT) From: Sumit Garg To: gregkh@linuxfoundation.org, daniel.thompson@linaro.org, dianders@chromium.org, linux-serial@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net Subject: [RFC 4/5] serial: amba-pl011: Enable NMI aware uart port Date: Tue, 21 Jul 2020 17:40:12 +0530 Message-Id: <1595333413-30052-5-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1595333413-30052-1-git-send-email-sumit.garg@linaro.org> References: <1595333413-30052-1-git-send-email-sumit.garg@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200721_081113_620636_C9B4CC38 X-CRM114-Status: GOOD ( 22.58 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sumit Garg , jslaby@suse.com, linux-kernel@vger.kernel.org, linux@armlinux.org.uk, jason.wessel@windriver.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Allow serial device interrupt to be requested as an NMI during initialization in polling mode. If the irqchip doesn't support serial device interrupt as an NMI then fallback to it being as a normal IRQ. Currently this NMI aware uart port only supports NMI driven programmed IO operation whereas DMA operation isn't supported. And 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. Also, get rid of modification to interrupts enable mask in pl011_hwinit() as now we have a proper way to enable interrupts for NMI entry using pl011_enable_interrupts(). Signed-off-by: Sumit Garg --- drivers/tty/serial/amba-pl011.c | 124 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0983c5e..5df1c07 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,96 @@ static void pl011_put_poll_char(struct uart_port *port, pl011_write(ch, uap, REG_DR); } +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_fifo_to_tty(uap); + irq_work_queue(&uap->port.nmi_state.rx_work); + } + + 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 +1828,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 +1838,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 +1883,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 +1955,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 +1990,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 +2244,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 +2275,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