From patchwork Mon Sep 26 14:12:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Holger Schurig X-Patchwork-Id: 9350741 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 E3B486077A for ; Mon, 26 Sep 2016 14:15:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D417528A70 for ; Mon, 26 Sep 2016 14:15:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C533628D73; Mon, 26 Sep 2016 14:15:19 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1724128E1C for ; Mon, 26 Sep 2016 14:15:16 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1boWf2-0006GY-8Y; Mon, 26 Sep 2016 14:13:36 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1boWev-00068A-6j for linux-arm-kernel@lists.infradead.org; Mon, 26 Sep 2016 14:13:33 +0000 Received: by mail-wm0-x241.google.com with SMTP id 133so14335837wmq.2 for ; Mon, 26 Sep 2016 07:13:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:mime-version; bh=DnXD3NgHG1JNNWZEDUov0usrH7rSFN9kmc+Pct+Nafo=; b=w+mcE/R/w/y7RTd54xZfNARCI7s/vrRlkznUMEk9uUTWL3atqas/NY8cKtngIwgqFH NeOEZLbZi39anTyVLz+z4uUkNj95TZJ8ECvu7rVlnti61W7U48wzZmg+6XJz6XUhcmTi EMF47byDysMyN3BOR6Vn+kayGUdmsgRMV6VcF6T66bEHBRsWJYXH33m7w5NRLXG9RRQ1 HJByVlL+NwASPWLdex33WdAs/aNZyZrb/vGkl6SmpQOqWbMyZXMqkOAteJdkk26OqnK1 E+VnpxNt5Mio3HddU/iZS35YGij8mX+JZ1a2ACwYpugs1xhh4JF99su9aIBCGZb9Xvj8 s44A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:mime-version; bh=DnXD3NgHG1JNNWZEDUov0usrH7rSFN9kmc+Pct+Nafo=; b=ilD269xoO2czxaQ4Q4+RUAJb8thWZGQchx3mu0oC7ydfCbo8JEc3hgb/8V2981V2+A WQCC/NZTu5XrcpBHADBaJoP3cV9Cn9FH20T+xRi/WB5W5KHKLWEvh6nt7g4rLOweC+8f t9XKoQ1WLW9c2q5Q2KQXarHJHpqdVe879ixgoH8F+x4q7IsTbkxvrpenw4cc1AZlM+k/ UToUraQeN0ThOuXLbCq7R3wgCJlDCz7D1dx2uYosFMR6eIYGpcU65F/hyBJpxSArkkhN Nv6Igjv+RP91cgEwbJea5aXUslqpxdiSvqd342CTqjBvnXC91slQuU+v4HsWJ33p40yU h76w== X-Gm-Message-State: AA6/9Rkna/q4ohrgwvOp83mLgYcC/A4LNSodL658m2vzHLxmM2+sUuZRO3yX1avia2xnrA== X-Received: by 10.28.208.134 with SMTP id h128mr13835646wmg.101.1474899186693; Mon, 26 Sep 2016 07:13:06 -0700 (PDT) Received: from desktop ([87.172.209.117]) by smtp.gmail.com with ESMTPSA id a1sm22615228wju.41.2016.09.26.07.13.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Sep 2016 07:13:05 -0700 (PDT) From: Holger Schurig To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Peter Hurley , linux-arm-kernel@lists.infradead.org Subject: BUG: serial: imx: imprecise data abort Date: Mon, 26 Sep 2016 16:12:58 +0200 Message-ID: <87y42eoil1.fsf@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160926_071329_531446_F3019542 X-CRM114-Status: GOOD ( 12.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Hi all, on an i.MX6Q we had a situation where we got "Imprecise Data Aborts". The backtraces of those aborts were useless, all over the place. But we found out that we can trigger this bug with this procedure: - make some external PC send constantly through the serial port to the i.MX6Q. - run a serial program on the i.MX6Q that receives the data and echos it back - let this program terminate and restart every over second (we used a 4 second interval) Chances were good that we reproduced the issue with various kernels (up to 4.7.2). In the drivers/tty/serial/tty/imx.c I disabled all DMA, because this was my first suspicion. But to no avail. Eventually we asked some company to help us. They produced the following patch. With this patch, we can now run for a long time without any imprecise data abort (actually we run into another issue, but according to https://lkml.org/lkml/2016/5/16/452 "tty crash in Linux 4.6" this is already in the working). It's entirely clear to me that below WIP-patch has ZERO chance of being added. It's not just checkpatch that will barf over it. :-) My goal is to make the more knowledgeable people aware of the issue and to give them a pointer, so that they can tell me how to fix the issue in a correct way. Holger spin_lock_irqsave(&sport->port.lock, flags); while (readl(sport->port.membase + USR2) & USR2_RDR) { + //skip if not enabled + if(((readl(sport->port.membase + UCR2) & UCR2_RXEN) ==0 ) + || ((readl(sport->port.membase + UCR1) & UCR1_UARTEN) ==0 )) + goto out; + flg = TTY_NORMAL; sport->port.icount.rx++; + + rx = readl(sport->port.membase + URXD0); @@ -735,6 +746,7 @@ unsigned int sts; unsigned int sts2; + atomic_add(1,&imx_uart_is_in_irq); sts = readl(sport->port.membase + USR1); sts2 = readl(sport->port.membase + USR2); @@ -761,7 +773,7 @@ sport->port.icount.overrun++; writel(USR2_ORE, sport->port.membase + USR2); } - + atomic_sub(1,&imx_uart_is_in_irq); return IRQ_HANDLED; } @@ -896,6 +908,7 @@ struct imx_port *sport = (struct imx_port *)data; unsigned long flags; + atomic_add(1,&imx_uart_is_in_irq); if (sport->port.state) { spin_lock_irqsave(&sport->port.lock, flags); imx_mctrl_check(sport); @@ -903,6 +916,7 @@ mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); } + atomic_sub(1,&imx_uart_is_in_irq); } #define RX_BUF_SIZE (PAGE_SIZE) @@ -1251,7 +1267,7 @@ } spin_lock_irqsave(&sport->port.lock, flags); imx_stop_tx(port); - imx_stop_rx(port); +// imx_stop_rx(port); imx_disable_dma(sport); spin_unlock_irqrestore(&sport->port.lock, flags); imx_uart_dma_exit(sport); @@ -1261,7 +1277,7 @@ spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); - temp &= ~(UCR2_TXEN); + //temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1276,13 +1292,16 @@ spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); - temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + //temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); writel(temp, sport->port.membase + UCR1); spin_unlock_irqrestore(&sport->port.lock, flags); - clk_disable_unprepare(sport->clk_per); - clk_disable_unprepare(sport->clk_ipg); + while(atomic_read(&imx_uart_is_in_irq) == 1); + + //clk_disable_unprepare(sport->clk_per); + //clk_disable_unprepare(sport->clk_ipg); } static void imx_flush_buffer(struct uart_port *port) @@ -1732,8 +1750,8 @@ if (locked) spin_unlock_irqrestore(&sport->port.lock, flags); - clk_disable(sport->clk_ipg); - clk_disable(sport->clk_per); + //clk_disable(sport->clk_ipg); + //clk_disable(sport->clk_per); } /* @@ -1834,7 +1852,7 @@ retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); - clk_disable(sport->clk_ipg); + /*clk_disable(sport->clk_ipg); if (retval) { clk_unprepare(sport->clk_ipg); goto error_console; @@ -1843,7 +1861,7 @@ retval = clk_prepare(sport->clk_per); if (retval) clk_disable_unprepare(sport->clk_ipg); - + */ error_console: return retval; } @@ -2034,7 +2052,7 @@ UCR1_TXMPTYEN | UCR1_RTSDEN); writel_relaxed(reg, sport->port.membase + UCR1); - clk_disable_unprepare(sport->clk_ipg); + //clk_disable_unprepare(sport->clk_ipg); /* * Allocate the IRQ(s) i.MX1 has three interrupts whereas later @@ -2136,7 +2154,7 @@ serial_imx_save_context(sport); - clk_disable(sport->clk_ipg); + //clk_disable(sport->clk_ipg); return 0; } @@ -2153,7 +2171,7 @@ serial_imx_restore_context(sport); - clk_disable(sport->clk_ipg); + //clk_disable(sport->clk_ipg); return 0; } --- linux-4.6.orig/drivers/tty/serial/imx.c +++ linux-4.6/drivers/tty/serial/imx.c @@ -234,6 +234,9 @@ unsigned int ucr3; }; +static unsigned int DBG_Starttx = 0; +atomic_t imx_uart_is_in_irq = ATOMIC_INIT(0); + static struct imx_uart_data imx_uart_devdata[] = { [IMX1_UART] = { .uts_reg = IMX1_UTS, @@ -386,8 +389,8 @@ } } - temp = readl(sport->port.membase + UCR2); - writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2); + //temp = readl(sport->port.membase + UCR2); + //writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2); /* disable the `Receiver Ready Interrrupt` */ temp = readl(sport->port.membase + UCR1); @@ -577,6 +580,7 @@ } if (!sport->dma_is_enabled) { + //DBG_Starttx++; temp = readl(sport->port.membase + UCR1); writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); }