Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp911222pxa; Wed, 12 Aug 2020 17:00:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwGP5yao8Iun7zjgV5abEM2R2ottsWrYwS4XiCx/+8Rk4BolWGVUNzu9pa4ibo+ed1SV2aD X-Received: by 2002:a17:906:a3d9:: with SMTP id ca25mr2344977ejb.164.1597276829179; Wed, 12 Aug 2020 17:00:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597276829; cv=none; d=google.com; s=arc-20160816; b=1HdA2JTwsTN29CWQCA3pvtd0LbX4ZYZ3ZNEgS5V4q4CCHLeoJps96I9gaCuizPBUHH w9a0ogXRVSnGanCf8mR+354eQ5uWbBMi6oSKtSXYK6W01iyVEVYy7ZtyBPhET94p0G1H njhUTULbyhHyiM12+M+1QAYySvf8n7xRxxWrQp12jcIf3RoFzdR1MLS+5e3KHxY+2rOT QnZqWCxUo9RZ2PLyTquikuwjxy+ftyqhYwyL4O/JlYbZSgUN2MPFIC0J5v8WeNSQg5Le yqVmCUQiezIkD2yHkT3Fe7CAFHbipEX6NOQ8ZWYAZ83rD4hh7MKTmpGPUqfmmXbI3l1K 3QfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=u7qNOlp2Vur+MwulA2oWBik1rL7NYguSARiGZDfJ2/c=; b=rp0BdCqwm62ZhPnXy9FnbfMXmBhoZ/+8U3V3CdiqsFapDyPn0iGAZ+xvTa6OUJuPUo Qqp0cDq1ouINvKIhYaiFiVagNQ8S7lCivnMzX+HqaS7yd2lWIZdcV58Ttjn7vowOPwM6 R27gVF2X9DCrYWdv8NxiEeS0ssHi9Svv5WQDhb/NnBkcZStRGa5f2vPAIErRFQ2NKiAi qtXqImbJMny7ydVABj3Nwb8q5Xu86xLjWCaQ1e8FDnyDq+gKXRo0ixE4XYYYTdXgROAr JA3nmb9M7N+UEBep4ItVFkQtAINYzvSxF1AwlM3kqIr/QxYPcUzaut+r4bld6v1FI2od zhHw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=nVBhsFMc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w9si2182299edq.487.2020.08.12.17.00.04; Wed, 12 Aug 2020 17:00:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=nVBhsFMc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726533AbgHLX7c (ORCPT + 99 others); Wed, 12 Aug 2020 19:59:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726518AbgHLX7b (ORCPT ); Wed, 12 Aug 2020 19:59:31 -0400 Received: from mail-vs1-xe41.google.com (mail-vs1-xe41.google.com [IPv6:2607:f8b0:4864:20::e41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1DFBC061384 for ; Wed, 12 Aug 2020 16:59:31 -0700 (PDT) Received: by mail-vs1-xe41.google.com with SMTP id 1so2031613vsl.1 for ; Wed, 12 Aug 2020 16:59:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=u7qNOlp2Vur+MwulA2oWBik1rL7NYguSARiGZDfJ2/c=; b=nVBhsFMc9jj0d4x5674347fTxX3ZWCz7PoqyAZ3t4pLNTapgA+qAg0Ha14vSlYc17u pexzSXEHiqxSbuE9Uto+K3yGQQEENH9un3Pv+jWCrHHFn35CJt+XbMLBl3UTxwHX7Hbe clzGbjWjvHz8LaC1tEgMBA+xIeti+12RxvWQo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=u7qNOlp2Vur+MwulA2oWBik1rL7NYguSARiGZDfJ2/c=; b=BBWiT/iOB3Mr4BTD0ZhFFAH06LA6kydBY/r9n9j6DnnveMsTNuGatW4pkGucx6ZNKe cirJy9L4uWXfqKnA6f/fLgdn9KzWWuR5s6CiHvclT7adA4I6fhS2IjwJ/xpVFgqgBH6Y j4tcGtW60W+N2WDEAtynXKigODRuuEUZMrkSIBDYIDv831Mb0fu6s3ecmXnu8Qw3b6WT 2UexxdyDrfm04c+gAIctE4iYjv468mTdO4vvY0tty2D4ndNyk2/3JzMeAPsUpmm41xee Y+JPJlOdurcQNrAKTluEtuJIIOknCG+wxXkcqPatgaOCSJuylPEJMlZ0SvQRy91cgnSb uEJw== X-Gm-Message-State: AOAM532kEFr+kuSxXKOEwuMlC3pQUcr9EuhFIX9Pfg1wEKE8PrNGO7V5 196A0BVb0fhtBjVYTSh0QvYljUcDRHQ= X-Received: by 2002:a05:6102:214c:: with SMTP id h12mr1310104vsg.218.1597276770027; Wed, 12 Aug 2020 16:59:30 -0700 (PDT) Received: from mail-vs1-f46.google.com (mail-vs1-f46.google.com. [209.85.217.46]) by smtp.gmail.com with ESMTPSA id t136sm548604vkb.38.2020.08.12.16.59.28 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 12 Aug 2020 16:59:28 -0700 (PDT) Received: by mail-vs1-f46.google.com with SMTP id a1so2027808vsp.4 for ; Wed, 12 Aug 2020 16:59:28 -0700 (PDT) X-Received: by 2002:a67:f44f:: with SMTP id r15mr1290216vsn.42.1597276767938; Wed, 12 Aug 2020 16:59:27 -0700 (PDT) MIME-Version: 1.0 References: <1595333413-30052-1-git-send-email-sumit.garg@linaro.org> <1595333413-30052-5-git-send-email-sumit.garg@linaro.org> In-Reply-To: <1595333413-30052-5-git-send-email-sumit.garg@linaro.org> From: Doug Anderson Date: Wed, 12 Aug 2020 16:59:16 -0700 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [RFC 4/5] serial: amba-pl011: Enable NMI aware uart port To: Sumit Garg Cc: Greg Kroah-Hartman , Daniel Thompson , linux-serial@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, Jiri Slaby , Russell King - ARM Linux , Jason Wessel , LKML , Linux ARM Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On Tue, Jul 21, 2020 at 5:11 AM Sumit Garg wrote: > > 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(-) Overall: I ran out of time to do a super full review, but presumably you're going to spin this series anyway and I'll look at it again then. For now a few things I noticed below... > 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) > +{ I wish there was a better way to share code between this and pl011_int(), but I guess it'd be too ugly? If nothing else it feels like you should do something to make it more obvious to anyone looking at them that they are sister functions and any change to one of them should be reflected in the other. Maybe they should be logically next to each other? > + 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); It feels like it might be beneficial to not call irq_work_queue() in a loop. It doesn't hurt but it feels like, at least, it's going to keep doing a bunch of atomic operations. It's not like it'll cause the work to run any sooner because it has to run on the same CPU, right? > + } > + > + if (status & UART011_TXIS) > + irq_work_queue(&uap->port.nmi_state.tx_work); Here too... > + > + 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; I don't think you want "goto clk_dis" here. > + > + /* 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; Wouldn't you also need to to somehow call free_nmi() in the error case? > + 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, Do we need to add a "free" at this point? > .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 > -- > 2.7.4 >