Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp748813ybt; Fri, 10 Jul 2020 11:20:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwGYm6/2ZxUMvqnCha6s3mrLFIolDdxUVdVjYlKCmcaCmIFJxG1q7Igu21grf7H8oPwtJCN X-Received: by 2002:a17:906:aac1:: with SMTP id kt1mr65622660ejb.408.1594405253950; Fri, 10 Jul 2020 11:20:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594405253; cv=none; d=google.com; s=arc-20160816; b=EB6V7R1X1jPYNlZC4F9V2aqV+cvp3rgHoMjoTOVYl2x4bHek0pIoMEUtBITu86paMG LV/5mcHO0E+WPXio/ZsdUPl6uwmCBzD61lqOTuKU+olIFY+7YGFuVpfHJhKcMMMCZE9C IRBnwyzrCDzUg5Cu0sIh3Kv2FT1Q2c4X++6exvHu/TP9R4BnTxY/RJQoYry3BSNt8oZB yxow/xH8z8zqg5yKg185gkpVhEEf06CoV6CUpCKwcKjbDNEdnMpv5CDJGSWzcpQCdTbe kyoc2tA4kBqjpi10z54PqWox7E1CHc221N7MJokocmJiXbcSZqtPEFgN2sRJU/gNE86J zQ8w== 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=wnOuOYXoizS/zBJcCxGZB+NxpIyUG/B4G9U+uO4vkR8=; b=eGjmdHNs2hvXxTYl1b6Z2FFm3zUYec/Z1S8+Q9WsiQ1Al1vOipJNpGJr+lzMkt7qkR 4f6y+kViz2arjo8+Ovbqmi4JaUGERfAxjpWZ2DvLBDtz46pZ6mN81hCjkhD2Cp8+Cj7N k3PjhnFNzRIAhM3Y3wdNUQJc6mSxFpWgWbi+1hLEHQrUfgLZ7s/6vICiI/K8uxVdMPjE cQcogaiL32/qcMnO+XOubmq3o9sdLDj7IyVBsWSzJvvGdlNsCM6WfZvEXW2SEh50LViw nO8Hei6CZ8rc8w8yIIN2JCvaBi8tLpybS+y2x8xVUH32lSMdWg0bOPv1gteCkIP0D/ey 9P5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=fIzKSved; 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 s14si4217551ejx.43.2020.07.10.11.20.30; Fri, 10 Jul 2020 11:20:53 -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=fIzKSved; 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 S1728059AbgGJSTn (ORCPT + 99 others); Fri, 10 Jul 2020 14:19:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728022AbgGJSTl (ORCPT ); Fri, 10 Jul 2020 14:19:41 -0400 Received: from mail-ua1-x942.google.com (mail-ua1-x942.google.com [IPv6:2607:f8b0:4864:20::942]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 628FBC08C5DD for ; Fri, 10 Jul 2020 11:19:40 -0700 (PDT) Received: by mail-ua1-x942.google.com with SMTP id j21so2098939ual.11 for ; Fri, 10 Jul 2020 11:19:40 -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=wnOuOYXoizS/zBJcCxGZB+NxpIyUG/B4G9U+uO4vkR8=; b=fIzKSvedd4Xt5WU2QaHjdRj4b+kQNS0g4OL/AbWRJroDEmFD6e2U7AfiGxiqLSrEsh cbA8OTFyZGQg4LPC7mhD+97Rsxo3xGQbiUQU07CTX/Jri44VcMEmEFLK3znjZyauLD2N Ti+2fqqRdC62TnnqThorhsp32v+sNHqM7B4z8= 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=wnOuOYXoizS/zBJcCxGZB+NxpIyUG/B4G9U+uO4vkR8=; b=NNIp4iH6lb04ULgdvBzYc/iEq/hruOzKTCzghg7KhS0Bda151NXXAcawn4rSOlerpV 217Gx8tMbt+SOY0fP2l+jcCASQKzmwVb7AxlOlaGcRUIMzLjooLii8zUz98tcfh2G0Q2 Zo2SBPd8o7rqvSKYrBH5Lj0LTlSel51/RyAKi4jyj5HdfZi59UiKH9xxKXoSFNU36M1J 7qsTYEfSyj0vjQRALs1R3P98HL7laWQ4EEtvoQwrMuJuWrXq2OrHjDQbcWGLE5JQQ1cr Dfh6FQVz+2BZyKMBZPvIkKunAzoWLOd0IUWfq4uRiqGqN678eSaHngLLduVhn4wLcoft l2pQ== X-Gm-Message-State: AOAM530FfzWHJA36Tv0irnpE+mRHT8g8efvbHx+7ynhZqMuftHksJQ1D cQU2Aihd8CQyGh/7SfKYNcimhvKKaN8= X-Received: by 2002:ab0:5b91:: with SMTP id y17mr53060582uae.95.1594405178869; Fri, 10 Jul 2020 11:19:38 -0700 (PDT) Received: from mail-vs1-f52.google.com (mail-vs1-f52.google.com. [209.85.217.52]) by smtp.gmail.com with ESMTPSA id r18sm894620vkf.49.2020.07.10.11.19.36 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 10 Jul 2020 11:19:37 -0700 (PDT) Received: by mail-vs1-f52.google.com with SMTP id x205so3457992vsc.11 for ; Fri, 10 Jul 2020 11:19:36 -0700 (PDT) X-Received: by 2002:a05:6102:20a:: with SMTP id z10mr43192375vsp.213.1594405176107; Fri, 10 Jul 2020 11:19:36 -0700 (PDT) MIME-Version: 1.0 References: <20200626200033.1528052-1-dianders@chromium.org> <20200626125844.1.I8546ecb6c5beb054f70c5302d1a7293484212cd1@changeid> In-Reply-To: From: Doug Anderson Date: Fri, 10 Jul 2020 11:19:24 -0700 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH 1/2] serial: qcom_geni_serial: Make kgdb work even if UART isn't console To: Evan Green Cc: Greg Kroah-Hartman , Daniel Thompson , Akash Asthana , Stephen Boyd , kgdb-bugreport@lists.sourceforge.net, linux-arm-msm , Sumit Garg , Vivek Gautam , Andy Gross , Bjorn Andersson , Jiri Slaby , LKML , linux-serial@vger.kernel.org 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 Fri, Jul 10, 2020 at 10:39 AM Evan Green wrote: > > On Fri, Jun 26, 2020 at 1:01 PM Douglas Anderson wrote: > > > > The geni serial driver had the rather sketchy hack in it where it > > would adjust the number of bytes per RX FIFO word from 4 down to 1 if > > it detected that CONFIG_CONSOLE_POLL was enabled (for kgdb) and this > > was a console port (defined by the kernel directing output to this > > port via the "console=" command line argument). > > > > The problem with that sketchy hack is that it's possible to run kgdb > > over a serial port even if it isn't used for console. > > > > Let's avoid the hack by simply handling the 4-bytes-per-FIFO word case > > for kdb. We'll have to have a (very small) cache but that should be > > fine. > > > > A nice side effect of this patch is that an agetty (or similar) > > running on this port is less likely to drop characters. We'll > > have roughly 4 times the RX FIFO depth than we used to now. > > > > NOTE: the character cache here isn't shared between the polling API > > and the non-polling API. That means that, technically, the polling > > API could eat a few extra bytes. This doesn't seem to pose a huge > > problem in reality because we'll only get several characters per FIFO > > word if those characters are all received at nearly the same time and > > we don't really expect non-kgdb characters to be sent to the same port > > as kgdb at the exact same time we're exiting kgdb. > > > > ALSO NOTE: we still have the sketchy hack for setting the number of > > bytes per TX FIFO word in place, but that one is less bad. kgdb > > doesn't have any problem with this because it always just sends 1 byte > > at a time and waits for it to finish. The TX FIFO hack is only really > > needed for console output. In any case, a future patch will remove > > that hack, too. > > > > Signed-off-by: Douglas Anderson > > --- > > > > drivers/tty/serial/qcom_geni_serial.c | 80 ++++++++++++++++++--------- > > 1 file changed, 55 insertions(+), 25 deletions(-) > > > > diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c > > index 0300867eab7a..4610e391e886 100644 > > --- a/drivers/tty/serial/qcom_geni_serial.c > > +++ b/drivers/tty/serial/qcom_geni_serial.c > > @@ -103,11 +103,13 @@ > > #define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4) > > #define IO_MACRO_IO2_IO3_SWAP 0x4640 > > > > -#ifdef CONFIG_CONSOLE_POLL > > -#define CONSOLE_RX_BYTES_PW 1 > > -#else > > -#define CONSOLE_RX_BYTES_PW 4 > > -#endif > > +struct qcom_geni_private_data { > > + /* NOTE: earlycon port will have NULL here */ > > + struct uart_driver *drv; > > + > > + u32 poll_cached_bytes; > > + unsigned int poll_cached_bytes_cnt; > > +}; > > > > struct qcom_geni_serial_port { > > struct uart_port uport; > > @@ -129,6 +131,8 @@ struct qcom_geni_serial_port { > > int wakeup_irq; > > bool rx_tx_swap; > > bool cts_rts_swap; > > + > > + struct qcom_geni_private_data private_data; > > }; > > > > static const struct uart_ops qcom_geni_console_pops; > > @@ -264,8 +268,9 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, > > unsigned int baud; > > unsigned int fifo_bits; > > unsigned long timeout_us = 20000; > > + struct qcom_geni_private_data *private_data = uport->private_data; > > > > - if (uport->private_data) { > > + if (private_data->drv) { > > port = to_dev_port(uport, uport); > > baud = port->baud; > > if (!baud) > > @@ -331,23 +336,42 @@ static void qcom_geni_serial_abort_rx(struct uart_port *uport) > > } > > > > #ifdef CONFIG_CONSOLE_POLL > > + > > static int qcom_geni_serial_get_char(struct uart_port *uport) > > { > > - u32 rx_fifo; > > + struct qcom_geni_private_data *private_data = uport->private_data; > > u32 status; > > + u32 word_cnt; > > + int ret; > > + > > + if (!private_data->poll_cached_bytes_cnt) { > > + status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); > > + writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); > > > > - status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); > > - writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); > > + status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); > > + writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); > > > > - status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); > > - writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); > > + status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); > > + word_cnt = status & RX_FIFO_WC_MSK; > > + if (!word_cnt) > > + return NO_POLL_CHAR; > > > > - status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); > > - if (!(status & RX_FIFO_WC_MSK)) > > - return NO_POLL_CHAR; > > + if (word_cnt == 1 && (status & RX_LAST)) > > I forget how the partial word snapping works. Are you sure you want > word_cnt == 1? I see qcom_geni_serial_handle_rx() looks at RX_LAST > independently as long as word_cnt != 0. I'm worried the hardware > allows one FIFO entry with say 2 bytes in it and RX_LAST set, but then > also piles new stuff in the FIFO behind it, so that word_cnt can be > >1. So I guess one point of evidence that the logic I have there is OK is that it works. :-P ...but also looking closer. Maybe first it's important to understand the REALLY WEIRD protocol that geni serial uses. This was discovered through a bunch of trial and error long ago when poking at how the driver worked. When you're reading from geni it essentially breaks things into packets. If you're midway through reading a packet of data and more bytes come in then geni will hide them from you until you read the whole packet. I'm not totally sure the exact conditions for when it decides to make a packet out of the data, but it's not important for this discussion. So when you read "RX_FIFO_WC" it tells you the total number of FIFO words in the current packet. That number will only ever go down. A packet is made up of some number of whole words plus one word that could be a whole word or could be a partial word. So if "RX_FIFO_WC" says 4 it means you've got 3 whole words (3 * 4 = 12 bytes) and one word that might be partial. You can find out about that one partial word (always the last word in the FIFO) by reading "RX_LAST" and "RX_LAST_BYTE_VALID". Once you finally read the last word in the FIFO then geni can tell you about the next packet of data. OK, so hopefully that made sense? So qcom_geni_serial_handle_rx() is trying to read ALL bytes. It first figures out the total count of bytes and then reads them all. That's why it needs to look at RX_LAST all the time. Also of note: RX_LAST only ever applies to the last word in the FIFO. If it was possible for the word count to grow _before_ fully clearing out the FIFO then it would be a race and software would never be able to tell which byte RX_LAST applied to. In the case of qcom_geni_serial_get_char() we don't want to read all bytes because we don't have a place to put them. We only want 1 byte but sometimes we're forced to read 4 because of the whole 4-bytes-per-fifo-entry thing. So we read one FIFO entry. As long as we're not reading the _last_ FIFO entry then geni won't start a new packet. So if RX_FIFO_WC > 1 and we read a byte then it'll go down by 1. If RX_FIFO_WC == 1 then we're reading the last entry and geni is allowed to start its next packet. > Also I mostly reviewed the change on Gerrit, they seemed to be the > same. In this case it was easier to understand the indentation > changes. If there were gotchas between the Gerrit version and this > patch, let me know. They are the same. -Doug