From patchwork Mon Feb 6 23:30:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 9558925 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 27716602B1 for ; Mon, 6 Feb 2017 23:33:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C96822638 for ; Mon, 6 Feb 2017 23:33:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1046726D05; Mon, 6 Feb 2017 23:33:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, T_DKIM_INVALID autolearn=no version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8C35722638 for ; Mon, 6 Feb 2017 23:33:46 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1casn3-00033E-8c; Mon, 06 Feb 2017 23:33:45 +0000 Received: from mail-pg0-f42.google.com ([74.125.83.42]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1casmy-0002za-Qv for linux-rockchip@lists.infradead.org; Mon, 06 Feb 2017 23:33:43 +0000 Received: by mail-pg0-f42.google.com with SMTP id 194so32456882pgd.2 for ; Mon, 06 Feb 2017 15:33:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id; bh=oxiP8ktA+ws5P7XsMuMLr2EJsRif4llUHvXRG+SabNE=; b=dLDco/N5mXYce77C9GVsrmJvvbpkZb8fxuwVeUJ2AOCCMn5hpeJoaoA6TE6yGIvz25 PVk2igmT1STDvivN2DQX3L/TfCLbXX9wq4AHiY9D022x9SrfkDzRybNC1FZMS+wKFF4f b1RHdPRCYAkENmet8MFCbLLWhicrb0l8QB6zI= 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; bh=oxiP8ktA+ws5P7XsMuMLr2EJsRif4llUHvXRG+SabNE=; b=M3pWhpf1cUYvDoOvaGsEWTlsyHD/5BTPVoUAWqrSLoUD7vlL0ZEiwZrjadJ+4Mqneg Vqf6evHlL1+jRmM1x+ibm70ekH6VPUstDZMWDAkAmEgfBoDfLNdLv08yzkJVSu7BGN/S XFI+B2ARDv5Mq4+kOI3BbF5ZRyOzbi8qieRoVaZGOntchw36X6niTd06jla6IinIkbfl xVaqRbX2jYR0SYZauKedJiVhijF8Sjz85Arv69Oiszod5T0oxTgKgB0MmQVhpHt/VNT7 uCm8SfVO0CFAqqoU4JxNfIlF6FJzYtaV9D2LOmhlAMaIh1UUG050CwrxT1XTfqm3/W0q ABBA== X-Gm-Message-State: AIkVDXKIWFqta3iAxIEqCxpPa/Mv0aH3CTp9w9i9Z3d6VeLih3pUMCHbU5AENvFIQaBWB7/z X-Received: by 10.84.217.202 with SMTP id d10mr21155243plj.53.1486423939216; Mon, 06 Feb 2017 15:32:19 -0800 (PST) Received: from tictac.mtv.corp.google.com ([172.22.65.76]) by smtp.gmail.com with ESMTPSA id q19sm5302890pfl.21.2017.02.06.15.32.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 06 Feb 2017 15:32:17 -0800 (PST) From: Douglas Anderson To: gregkh@linuxfoundation.org, jslaby@suse.com Subject: [PATCH v2] serial: 8250_dw: Avoid "too much work" from bogus rx timeout interrupt Date: Mon, 6 Feb 2017 15:30:00 -0800 Message-Id: <20170206233000.3021-1-dianders@chromium.org> X-Mailer: git-send-email 2.11.0.483.g087da7b7c-goog X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170206_153340_901311_8BD9828E X-CRM114-Status: GOOD ( 16.90 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: wangkefeng.wang@huawei.com, briannorris@chromium.org, guennadi.liakhovetski@intel.com, ed.blake@imgtec.com, jeffy.chen@rock-chips.com, Douglas Anderson , linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, jason.uy@broadcom.com, eric.gao@rock-chips.com, california.l.sullivan@intel.com, linux-serial@vger.kernel.org, heikki.krogerus@linux.intel.com, noamc@ezchip.com, andriy.shevchenko@linux.intel.com MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP On a Rockchip rk3399-based board during suspend/resume testing, we found that we could get the console UART into a state where it would print this to the console a lot: serial8250: too much work for irq42 Followed eventually by: NMI watchdog: BUG: soft lockup - CPU#0 stuck for 11s! Upon debugging I found that we're in this state: iir = 0x000000cc lsr = 0x00000060 It appears that somehow we have a RX Timeout interrupt but there is no actual data present to receive. When we're in this state the UART driver claims that it handled the interrupt but it actually doesn't really do anything. This means that we keep getting the interrupt over and over again. Normally we don't actually need to do anything special to handle a RX Timeout interrupt. We'll notice that there is some data ready and we'll read it, which will end up clearing the RX Timeout. In this case we have a problem specifically because we got the RX TImeout without any data. Reading a bogus byte is confirmed to get us out of this state. It's unclear how exactly the UART got into this state, but it is known that the UART lines are essentially undriven and unpowered during suspend, so possibly during resume some garbage / half transmitted bits are seen on the line and put the UART into this state. The UART on the rk3399 is a DesignWare based 8250 UART. From mailing list posts, it appears that other people have run into similar problems with DesignWare based IP. Presumably this problem is unique to that IP, so I have placed the workaround there to avoid possibly of accidentally triggering bad behavior on other IP. Also note the RX Timeout behaves very differently in the DMA case, for for now the workaround is only applied to the non-DMA case. Signed-off-by: Douglas Anderson --- Testing and development done on a kernel-4.4 based tree, then picked to ToT, where the code applied cleanly. Changes in v2: - Only apply to 8250_dw, not all 8250 - Only apply to the non-DMA case drivers/tty/serial/8250/8250_dw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index c89ae4581378..6ee55a2d47bb 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -201,8 +201,31 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) static int dw8250_handle_irq(struct uart_port *p) { + struct uart_8250_port *up = up_to_u8250p(p); struct dw8250_data *d = p->private_data; unsigned int iir = p->serial_in(p, UART_IIR); + unsigned int status; + unsigned long flags; + + /* + * There are ways to get Designware-based UARTs into a state where + * they are asserting UART_IIR_RX_TIMEOUT but there is no actual + * data available. If we see such a case then we'll do a bogus + * read. If we don't do this then the "RX TIMEOUT" interrupt will + * fire forever. + * + * This problem has only been observed so far when not in DMA mode + * so we limit the workaround only to non-DMA mode. + */ + if (!up->dma && ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)) { + spin_lock_irqsave(&p->lock, flags); + status = p->serial_in(p, UART_LSR); + + if (!(status & (UART_LSR_DR | UART_LSR_BI))) + (void) p->serial_in(p, UART_RX); + + spin_unlock_irqrestore(&p->lock, flags); + } if (serial8250_handle_irq(p, iir)) return 1;