From patchwork Thu Aug 3 13:01:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339964 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 732A0C04A6A for ; Thu, 3 Aug 2023 13:02:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=uZWw+hOpfer9XBrJbkDW3D/A4I82j4DsM1iS4vYofFw=; b=XBetINIwGFRXDo 6gxBvW4QKheLhlztPP+rCncOAPM06RE4KCcb68gyzCffuj9HNjAVSg1lDhowaASe0xwI+jvWcRPLH g0E6FhXQIn+GmTbMPvm370sp6uDmMdqqHTLH5Br2UXWKDI74hYMzgCpswwyhst2UjgZEJ/T1QSisG J/vGaJr3JNMnpZqR51WIhK0LxCFmCOr7/IiTjrrYys+/jRHxIFh7Ll64DgREReJ+08CUGxyfMhRF3 pNUCX32q6MJP6KVFtr+hBp1NtTY2kAyx7sH2JUFUmKN5zfS0tb8RURcRXAvWlYCUKzKEA6qgSj2RM Bu/6a9Lv2e4SPMwb65Ig==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyD-008jYo-1V; Thu, 03 Aug 2023 13:02:25 +0000 Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXy7-008jQS-0z for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:02:21 +0000 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373CeU77009011; Thu, 3 Aug 2023 15:02:01 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=dhCwEHX0DJwZiRNK4fFfUdVG5e5HKjrWxTyeEHdpYQ0=; b=8X vBbiD6lFc9GDgjpLi6Miyx+PGKelcK8MmhsOqLecGp64gVvFaE6KloYjqc2j6XEr gCZjFFx5lKx82I18sfdNs0a6b6DCcnwLIrcLGbExm3X4NaV6wUSO+WH3/ZBXaOx/ 7kEMxbQFU1IU2b81WvfRnnxj7/QaQe1jI6bN27vG65/C2lsex7M7zh79wUl37Qoo Er3888kbBI5JX0iDu/8gp4JCQwZxWZx4qECFWU+HZnubK4GtliEjoTUmN4c8kjo+ QeV9kCjJC6EBdvLbXRczBx6tsvVNBZmL8pGCo/oK3S2ekp8HMUi08llKSIZ5ImBC C+QcsRM2q7SMEjOltduA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s8cet04b4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:02:01 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 2090510008C; Thu, 3 Aug 2023 15:01:58 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 17A6C2171E3; Thu, 3 Aug 2023 15:01:58 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:01:57 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 1/6] serial: stm32: avoid clearing DMAT bit during transfer Date: Thu, 3 Aug 2023 15:01:29 +0200 Message-ID: <20230803130134.155355-2-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060219_699606_D7D4C03B X-CRM114-Status: GOOD ( 19.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org It's rather advised to rely on DMA pause / resume instead of clearing/setting DMA request enable bit for the same purpose. Some DMA request/acknowledge race may encountered by doing so. We prefer to use dmaengine_pause and resume instead to pause a dma transfer when it is necessary. It is also safer to close DMA before reset DMAT in stm32_usart_shutdown. Signed-off-by: Valentin Caron --- drivers/tty/serial/stm32-usart.c | 76 ++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index be47cd343cf6..2f9672ba4ed3 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -506,13 +506,6 @@ static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port) return stm32_port->tx_dma_busy; } -static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port) -{ - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - - return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) & USART_CR3_DMAT); -} - static void stm32_usart_tx_dma_complete(void *arg) { struct uart_port *port = arg; @@ -591,9 +584,6 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - if (stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) @@ -616,10 +606,16 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) struct circ_buf *xmit = &port->state->xmit; struct dma_async_tx_descriptor *desc = NULL; unsigned int count; + int ret; if (stm32_usart_tx_dma_started(stm32port)) { - if (!stm32_usart_tx_dma_enabled(stm32port)) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); + if (dmaengine_tx_status(stm32port->tx_ch, + stm32port->tx_ch->cookie, + NULL) == DMA_PAUSED) { + ret = dmaengine_resume(stm32port->tx_ch); + if (ret < 0) + goto dma_err; + } return; } @@ -664,11 +660,9 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) desc->callback_param = port; /* Push current DMA TX transaction in the pending queue */ - if (dma_submit_error(dmaengine_submit(desc))) { - /* dma no yet started, safe to free resources */ - stm32_usart_tx_dma_terminate(stm32port); - goto fallback_err; - } + /* DMA no yet started, safe to free resources */ + if (dma_submit_error(dmaengine_submit(desc))) + goto dma_err; /* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); @@ -679,6 +673,10 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) return; +dma_err: + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_tx_dma_terminate(stm32port); + fallback_err: stm32_usart_transmit_chars_pio(port); } @@ -701,9 +699,15 @@ static void stm32_usart_transmit_chars(struct uart_port *port) if (port->x_char) { if (stm32_usart_tx_dma_started(stm32_port) && - stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - + dmaengine_tx_status(stm32_port->tx_ch, + stm32_port->tx_ch->cookie, + NULL) == DMA_IN_PROGRESS) { + ret = dmaengine_pause(stm32_port->tx_ch); + if (ret < 0) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_tx_dma_terminate(stm32_port); + } + } /* Check that TDR is empty before filling FIFO */ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, @@ -716,8 +720,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port) writel_relaxed(port->x_char, port->membase + ofs->tdr); port->x_char = 0; port->icount.tx++; - if (stm32_usart_tx_dma_started(stm32_port)) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); + + if (stm32_usart_tx_dma_started(stm32_port)) { + ret = dmaengine_resume(stm32_port->tx_ch); + if (ret < 0) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_tx_dma_terminate(stm32_port); + } + } return; } @@ -850,11 +860,16 @@ static void stm32_usart_disable_ms(struct uart_port *port) static void stm32_usart_stop_tx(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + int ret; stm32_usart_tx_interrupt_disable(port); - if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + if (stm32_usart_tx_dma_started(stm32_port)) { + ret = dmaengine_pause(stm32_port->tx_ch); + if (ret < 0) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_tx_dma_terminate(stm32_port); + } + } stm32_usart_rs485_rts_disable(port); } @@ -878,12 +893,9 @@ static void stm32_usart_start_tx(struct uart_port *port) static void stm32_usart_flush_buffer(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - if (stm32_port->tx_ch) { + if (stm32_port->tx_ch) stm32_usart_tx_dma_terminate(stm32_port); - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - } } /* Throttle the remote when input buffer is about to overflow. */ @@ -1042,12 +1054,12 @@ static void stm32_usart_shutdown(struct uart_port *port) u32 val, isr; int ret; - if (stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - if (stm32_usart_tx_dma_started(stm32_port)) stm32_usart_tx_dma_terminate(stm32_port); + if (stm32_port->tx_ch) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + /* Disable modem control interrupts */ stm32_usart_disable_ms(port); From patchwork Thu Aug 3 13:01:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339960 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3343BC001DF for ; Thu, 3 Aug 2023 13:02:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=fqL4fhoOCabHYafqGJoSFgok9IyFG94j/1sdCeFL5Nc=; b=WqNFjOhitovVM1 nfH2ZJ++orE02uYsKhaFgCtjAqHO+reA3Udelok0T5XUtjyB47XwVPhW7psFeYX5JfgaACRlJ5Xt5 AaSyDHvTSTOxTHBmCEDPxAo3tTBCMS78C8tFxnv2AoXxZcZznccckxSlc7YebcUzkazDb+0T0YDzC RJYVhYbwx5mvCfHNykBWObkeLBOhsKuWYJiyR3sjoVa/QJLnz5Iq3cO+eRxdvndGbAqG227D8gcXz PIfJ2oQNMSWmMcfn32Fr0iBAeX6610BIve61jtingf+lBTnLpsU8IVnadJiEnNNVGtOy751tTna+f LFiafSqHfTgy/M76QJKw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyE-008jZX-0I; Thu, 03 Aug 2023 13:02:26 +0000 Received: from mx07-00178001.pphosted.com ([185.132.182.106]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXy8-008jPA-0q for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:02:22 +0000 Received: from pps.filterd (m0288072.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373CPmGe001957; Thu, 3 Aug 2023 15:01:59 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=H3iC7kCgn+jbf9xv4NCtbx4bJ9rUCRO56BhrTEOCRhU=; b=W2 55ecaM4+vY6A9BlIx4eMs4Z+flEsSTVfw4FtZDUv83GCCNIXiiE9TTLtFsZ8iR/a takE8lMO40G3GsT+c6a6SS3p9pEHvd9S0DIqvQGc4IeUD2evJvpzGDYu/CtE8yLx ruUoDIH1NOlf0sWCIVfEYBHc+ZVQmfvvfOvMz/dOYGBJ/xyLdctP+QLsH/Ln96dL kpN9tBJEAa2tko5fXLzQsuOkMCa3wa3Z24681K70hJIghVcDxdTIglfTa5Y4qa9R uA+qyP+VAN7zD6745BaI3LViiLnJfXgnxhGceTFfpmtUgV0uk2sH9CTvu1+AE+0d Ju7AXMc0AG2OIHA678FA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s893bhkfw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:01:59 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id EA80910008D; Thu, 3 Aug 2023 15:01:58 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id E235A2171E2; Thu, 3 Aug 2023 15:01:58 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:01:58 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 2/6] serial: stm32: use DMAT as a configuration bit Date: Thu, 3 Aug 2023 15:01:30 +0200 Message-ID: <20230803130134.155355-3-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060220_630963_D4F7347D X-CRM114-Status: GOOD ( 15.20 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DMAT is a configuration bit so it should be set at the startup of uart port and not when a DMA transfer begins. This patch move set of DMAT into set_termios and remove DMAT reset except in shutdown. Signed-off-by: Valentin Caron --- drivers/tty/serial/stm32-usart.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 2f9672ba4ed3..a1585aa1ceb0 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -510,10 +510,8 @@ static void stm32_usart_tx_dma_complete(void *arg) { struct uart_port *port = arg; struct stm32_port *stm32port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; unsigned long flags; - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32_usart_tx_dma_terminate(stm32port); /* Let's see if we have pending data to send */ @@ -602,7 +600,6 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) static void stm32_usart_transmit_chars_dma(struct uart_port *port) { struct stm32_port *stm32port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; struct circ_buf *xmit = &port->state->xmit; struct dma_async_tx_descriptor *desc = NULL; unsigned int count; @@ -667,8 +664,6 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) /* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); - uart_xmit_advance(port, count); return; @@ -1270,6 +1265,9 @@ static void stm32_usart_set_termios(struct uart_port *port, cr3 |= USART_CR3_DDRE; } + if (stm32_port->tx_ch) + cr3 |= USART_CR3_DMAT; + if (rs485conf->flags & SER_RS485_ENABLED) { stm32_usart_config_reg_rs485(&cr1, &cr3, rs485conf->delay_rts_before_send, From patchwork Thu Aug 3 13:01:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339961 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6CBF5C04A94 for ; Thu, 3 Aug 2023 13:02:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=daUqEc3C1dP0z9wao7hP7a/yHvF6ZM1lhIef+UBLbmo=; b=oWu8SUj+P9f7gp rkGmGafzjs5jKKjeQH4HOINcFa5yRPHElPSoKlUA8rAzGk/dK/84y0lEieLApc/Y+cBGLkYXPFloA oky3677NJ9DkDXVrrcz7AM21FGKPCwi+Z+RmQqDT2djZKgs9DNe/20vWpyOq380Dr1aNSCUpEop/w hEPfkjhJSwvdi73jXreDOMHbN2197KV2jpC3xEP/gWIEOfD364Q0xKhXRNEPgBnubja056efvSO7/ LBw5/7uLa1l8UmEneuGbbwQ2VgO7VK66cmfziwu3a56dlZjEQP8neAsy+mEZ5I4har+Ns4gCWYaD3 6ul8XzPDfZXMsHJaA9hA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyC-008jY6-1l; Thu, 03 Aug 2023 13:02:24 +0000 Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXy7-008jQO-0k for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:02:21 +0000 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373CeWsj009022; Thu, 3 Aug 2023 15:02:01 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=sDVdmzlOw9KaqcJOaAInkeyF4AR3n6Sh8qLWXt91jcU=; b=DI OY9izIwHeVXMDnFFYO0fI6ZH+89bQSc7X/lJ9HWHY9R2UjHpp2KVNqulqeF4Ex62 HVBnqtR/bJrOMTxJzxwtnIUNfqPEvmUCaM6FoVXJ9LQ5GculU9PAw3sUkRyeyNgR da5DkvBxXh0UwvyZB6mVwLA3RSCo79pWo8GxCXR7LMhj12hwKoU2qR9kEdNyI/cq KdaghMlEL0X1kgIw9Z4EXpkn33WpeVq/7pnwzehQOcBt5x201xqRW8VEuFaqE1Ux 8YMSEHvHXk4A6l0jYpWwS0sMoLCAhSS8SPVsSGNon4s+lvdcGkU8pDAlIkhsZI6G Cpq39pSV/P1vrtUsTFEw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s8cet04b8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:02:01 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id C096C10008E; Thu, 3 Aug 2023 15:01:59 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id B8E392171E2; Thu, 3 Aug 2023 15:01:59 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:01:59 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 3/6] serial: stm32: modify parameter and rename stm32_usart_rx_dma_enabled Date: Thu, 3 Aug 2023 15:01:31 +0200 Message-ID: <20230803130134.155355-4-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060219_582476_66845E0A X-CRM114-Status: GOOD ( 16.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Rename stm32_usart_rx_dma_enabled to stm32_usart_rx_dma_started in order to match with stm32_usart_tx_dma_started. Modify argument of stm32_usart_rx_dma_started from uart_port structure to stm32_port structure to match with stm32_usart_tx_dma_started. Signed-off-by: Valentin Caron --- drivers/tty/serial/stm32-usart.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index a1585aa1ceb0..3471e23bb02f 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -289,9 +289,9 @@ static int stm32_usart_init_rs485(struct uart_port *port, return uart_get_rs485_mode(port); } -static bool stm32_usart_rx_dma_enabled(struct uart_port *port) +static bool stm32_usart_rx_dma_started(struct stm32_port *stm32_port) { - struct stm32_port *stm32_port = to_stm32_port(port); + struct uart_port *port = &stm32_port->port; const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; if (!stm32_port->rx_ch) @@ -310,7 +310,7 @@ static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr) /* Get pending characters in RDR or FIFO */ if (*sr & USART_SR_RXNE) { /* Get all pending characters from the RDR or the FIFO when using interrupts */ - if (!stm32_usart_rx_dma_enabled(port)) + if (!stm32_usart_rx_dma_started(stm32_port)) return true; /* Handle only RX data errors when using DMA */ @@ -455,7 +455,7 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force u32 sr; unsigned int size = 0; - if (stm32_usart_rx_dma_enabled(port) || force_dma_flush) { + if (stm32_usart_rx_dma_started(stm32_port) || force_dma_flush) { rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, stm32_port->rx_ch->cookie, &stm32_port->rx_dma_state); @@ -789,8 +789,8 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) * line has been masked by HW and rx data are stacking in FIFO. */ if (!stm32_port->throttled) { - if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) || - ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port))) { + if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_started(stm32_port)) || + ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_started(stm32_port))) { spin_lock(&port->lock); size = stm32_usart_receive_chars(port, false); uart_unlock_and_check_sysrq(port); @@ -806,7 +806,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) } /* Receiver timeout irq for DMA RX */ - if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) { + if (stm32_usart_rx_dma_started(stm32_port) && !stm32_port->throttled) { spin_lock(&port->lock); size = stm32_usart_receive_chars(port, false); uart_unlock_and_check_sysrq(port); @@ -906,7 +906,7 @@ static void stm32_usart_throttle(struct uart_port *port) * Disable DMA request line if enabled, so the RX data gets queued into the FIFO. * Hardware flow control is triggered when RX FIFO is full. */ - if (stm32_usart_rx_dma_enabled(port)) + if (stm32_usart_rx_dma_started(stm32_port)) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); From patchwork Thu Aug 3 13:01:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339962 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C9008C001DF for ; Thu, 3 Aug 2023 13:02:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=T9/xOMuwetiETssM9ea1nYyhWal8ep56zC0CFu/w6tI=; b=Vd739xuY3nMGKG lyN357cDFbGoEpOl3ICoSid+OOC6xZk2T+dpXHRlGl6u0GZLp4+gk648Q8mhVfNcHlUHrxuIegnQq ssKo+4Dk5a3M9onH4GjDaKTwdVfIIFafzpyB88VKk/5KplaJG3FF2Ck9ymJqoiVbK4lGGKEMVf0Rl zEsGRGm4VqF5fQeAL5eAvZPmfmpbuOb/eCiXW0UxWKQl3iPn4OQ/xgFhZYIKEF5B/DYu6LgDKOPdh W2tQm8AzoiNMuJUaC1P7Dj2NScOWZaOxDBY67ZhnW8tyWR6UU56A2MFznFGqpdr+GYXGY5p1O0bZk ybVbD6JB4abuxAXutnSQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXy9-008jW0-2O; Thu, 03 Aug 2023 13:02:21 +0000 Received: from mx07-00178001.pphosted.com ([185.132.182.106]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXy5-008jQQ-1J for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:02:19 +0000 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373A02BF010199; Thu, 3 Aug 2023 15:02:02 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=7WIfw0irEIV+Oza8xiL4BFzi+kqQJHgoFXmjppWCvUw=; b=OW sBI+3Kd5M8GYseRFWNewGDnQGn/ttvmm31qzFqGcPhzXqvGM2Z6zbhEtLVsKGX5U VtiTpQri/gXCoNdBf4OVJM4n4YRTkofm2yGrPUT6s58aK4PJ17k3G0iSu11i03wX TeoGR+hqtcCZFW0GVlpy1L6Dh1MmzwyC+xFP4p//v9fcxQYXXz7bnAqkhaD8M79S QRHzCt8KT9RwR5sM5gT3xpT/kuYi3JckJu84KgRRMjfBy9I4RE+ocWzmzPzdjkX9 RZm3onXg3J4gehNDZwLixY8FLgOSK9EVhtCkSeiXQA6abjxLkCdlsXkSQWXsdyV/ X6dPz04VhwlAYbLB/ElA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s8a3qh1h9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:02:02 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 9A0C510008F; Thu, 3 Aug 2023 15:02:00 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 91EA42171E3; Thu, 3 Aug 2023 15:02:00 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:02:00 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 4/6] serial: stm32: group dma pause/resume error handling into single function Date: Thu, 3 Aug 2023 15:01:32 +0200 Message-ID: <20230803130134.155355-5-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060217_981274_0A9AE348 X-CRM114-Status: GOOD ( 22.15 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Create new function "stm32_usart_dma_pause_resume" that called dmaengine_ pause/resume and in case of error, terminate dma transaction. Two other functions are created to facilitate the use of stm32_usart_dma _pause_resume : stm32_usart_tx_dma_pause, stm32_usart_tx_dma_resume. Equivalent functions for rx will be added in future patch. Signed-off-by: Valentin Caron --- drivers/tty/serial/stm32-usart.c | 127 ++++++++++++++++++++----------- drivers/tty/serial/stm32-usart.h | 1 + 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 3471e23bb02f..0dae05a7abe6 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -290,14 +290,40 @@ static int stm32_usart_init_rs485(struct uart_port *port, } static bool stm32_usart_rx_dma_started(struct stm32_port *stm32_port) +{ + return stm32_port->rx_ch ? stm32_port->rx_dma_busy : false; +} + +static void stm32_usart_rx_dma_terminate(struct stm32_port *stm32_port) +{ + dmaengine_terminate_async(stm32_port->rx_ch); + stm32_port->rx_dma_busy = false; +} + +static int stm32_usart_dma_pause_resume(struct stm32_port *stm32_port, + struct dma_chan *chan, + enum dma_status expected_status, + int dmaengine_pause_or_resume(struct dma_chan *), + bool stm32_usart_xx_dma_started(struct stm32_port *), + void stm32_usart_xx_dma_terminate(struct stm32_port *)) { struct uart_port *port = &stm32_port->port; - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + enum dma_status dma_status; + int ret; + + if (!stm32_usart_xx_dma_started(stm32_port)) + return -EPERM; - if (!stm32_port->rx_ch) - return false; + dma_status = dmaengine_tx_status(chan, chan->cookie, NULL); + if (dma_status != expected_status) + return -EAGAIN; - return !!(readl_relaxed(port->membase + ofs->cr3) & USART_CR3_DMAR); + ret = dmaengine_pause_or_resume(chan); + if (ret) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_xx_dma_terminate(stm32_port); + } + return ret; } /* Return true when data is pending (in pio mode), and false when no data is pending. */ @@ -475,7 +501,7 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force } } else { /* Disable RX DMA */ - dmaengine_terminate_async(stm32_port->rx_ch); + stm32_usart_rx_dma_terminate(stm32_port); stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); /* Fall back to interrupt mode */ dev_dbg(port->dev, "DMA error, fallback to irq mode\n"); @@ -506,6 +532,22 @@ static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port) return stm32_port->tx_dma_busy; } +static int stm32_usart_tx_dma_pause(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->tx_ch, + DMA_IN_PROGRESS, dmaengine_pause, + stm32_usart_tx_dma_started, + stm32_usart_tx_dma_terminate); +} + +static int stm32_usart_tx_dma_resume(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->tx_ch, + DMA_PAUSED, dmaengine_resume, + stm32_usart_tx_dma_started, + stm32_usart_tx_dma_terminate); +} + static void stm32_usart_tx_dma_complete(void *arg) { struct uart_port *port = arg; @@ -606,13 +648,9 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) int ret; if (stm32_usart_tx_dma_started(stm32port)) { - if (dmaengine_tx_status(stm32port->tx_ch, - stm32port->tx_ch->cookie, - NULL) == DMA_PAUSED) { - ret = dmaengine_resume(stm32port->tx_ch); - if (ret < 0) - goto dma_err; - } + ret = stm32_usart_tx_dma_resume(stm32port); + if (ret < 0 && ret != -EAGAIN) + goto fallback_err; return; } @@ -658,8 +696,12 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) /* Push current DMA TX transaction in the pending queue */ /* DMA no yet started, safe to free resources */ - if (dma_submit_error(dmaengine_submit(desc))) - goto dma_err; + ret = dma_submit_error(dmaengine_submit(desc)); + if (ret) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_tx_dma_terminate(stm32port); + goto fallback_err; + } /* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); @@ -668,10 +710,6 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) return; -dma_err: - dev_err(port->dev, "DMA failed with error code: %d\n", ret); - stm32_usart_tx_dma_terminate(stm32port); - fallback_err: stm32_usart_transmit_chars_pio(port); } @@ -693,16 +731,9 @@ static void stm32_usart_transmit_chars(struct uart_port *port) } if (port->x_char) { - if (stm32_usart_tx_dma_started(stm32_port) && - dmaengine_tx_status(stm32_port->tx_ch, - stm32_port->tx_ch->cookie, - NULL) == DMA_IN_PROGRESS) { - ret = dmaengine_pause(stm32_port->tx_ch); - if (ret < 0) { - dev_err(port->dev, "DMA failed with error code: %d\n", ret); - stm32_usart_tx_dma_terminate(stm32_port); - } - } + /* dma terminate may have been called in case of dma pause failure */ + stm32_usart_tx_dma_pause(stm32_port); + /* Check that TDR is empty before filling FIFO */ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, @@ -716,13 +747,8 @@ static void stm32_usart_transmit_chars(struct uart_port *port) port->x_char = 0; port->icount.tx++; - if (stm32_usart_tx_dma_started(stm32_port)) { - ret = dmaengine_resume(stm32_port->tx_ch); - if (ret < 0) { - dev_err(port->dev, "DMA failed with error code: %d\n", ret); - stm32_usart_tx_dma_terminate(stm32_port); - } - } + /* dma terminate may have been called in case of dma resume failure */ + stm32_usart_tx_dma_resume(stm32_port); return; } @@ -855,16 +881,11 @@ static void stm32_usart_disable_ms(struct uart_port *port) static void stm32_usart_stop_tx(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); - int ret; stm32_usart_tx_interrupt_disable(port); - if (stm32_usart_tx_dma_started(stm32_port)) { - ret = dmaengine_pause(stm32_port->tx_ch); - if (ret < 0) { - dev_err(port->dev, "DMA failed with error code: %d\n", ret); - stm32_usart_tx_dma_terminate(stm32_port); - } - } + + /* dma terminate may have been called in case of dma pause failure */ + stm32_usart_tx_dma_pause(stm32_port); stm32_usart_rs485_rts_disable(port); } @@ -965,8 +986,22 @@ static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct dma_async_tx_descriptor *desc; + enum dma_status rx_dma_status; int ret; + if (stm32_port->rx_dma_busy) { + rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, + stm32_port->rx_ch->cookie, + NULL); + if (rx_dma_status == DMA_IN_PROGRESS) + return 0; + + dev_err(port->dev, "DMA failed : status error.\n"); + stm32_usart_rx_dma_terminate(stm32_port); + } + + stm32_port->rx_dma_busy = true; + stm32_port->last_res = RX_BUF_L; /* Prepare a DMA cyclic transaction */ desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch, @@ -976,6 +1011,7 @@ static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) DMA_PREP_INTERRUPT); if (!desc) { dev_err(port->dev, "rx dma prep cyclic failed\n"); + stm32_port->rx_dma_busy = false; return -ENODEV; } @@ -986,6 +1022,7 @@ static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) ret = dma_submit_error(dmaengine_submit(desc)); if (ret) { dmaengine_terminate_sync(stm32_port->rx_ch); + stm32_port->rx_dma_busy = false; return ret; } @@ -1074,7 +1111,7 @@ static void stm32_usart_shutdown(struct uart_port *port) /* Disable RX DMA. */ if (stm32_port->rx_ch) - dmaengine_terminate_async(stm32_port->rx_ch); + stm32_usart_rx_dma_terminate(stm32_port); /* flush RX & TX FIFO */ if (ofs->rqr != UNDEF_REG) @@ -1988,7 +2025,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); /* Poll data from DMA RX buffer if any */ size = stm32_usart_receive_chars(port, true); - dmaengine_terminate_async(stm32_port->rx_ch); + stm32_usart_rx_dma_terminate(stm32_port); uart_unlock_and_check_sysrq_irqrestore(port, flags); if (size) tty_flip_buffer_push(tport); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 903285b5aea7..f59f831b2a10 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -199,6 +199,7 @@ struct stm32_port { u32 cr3_irq; /* USART_CR3_RXFTIE */ int last_res; bool tx_dma_busy; /* dma tx transaction in progress */ + bool rx_dma_busy; /* dma rx transaction in progress */ bool throttled; /* port throttled */ bool hw_flow_control; bool swap; /* swap RX & TX pins */ From patchwork Thu Aug 3 13:01:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339966 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4B5B9C001DF for ; Thu, 3 Aug 2023 13:03:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=musPUzDlWL+JPq8VuLt08QGpmKvTJR5f8cY2z7GkqgA=; b=WHS8egaHhTfMRs +yexTcWAjgCENah0KA9jQF+F/EQoHY/TRZXste+CJIBAz3pxNrwKZKaKsPdlPh9HBw6QmydBUsjJ5 nj+ahzVVVJ2pMi0M1DeLe1kVaalOKsHyG9kFaPiIYzj7QInqktllWbTVvNKlnNtdLCduvM+SkLJ9l quWt3QR4yzjMmUu6Cr67TC8pZUjtJPlTflJvH6R2rwVopRssHfwfI4x5CWXvP770zx/xPO+QVXRyM J8yiADLKzEJuwMLc1N1QE98vrZqpePGO6qUuehszdwTyeQnV44rX+g1xqp7nwySd2t7sNbwCehNTs ieiw/TMX88FVobBuOxpQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyx-008k8z-2g; Thu, 03 Aug 2023 13:03:11 +0000 Received: from mx07-00178001.pphosted.com ([185.132.182.106]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyt-008k52-2v for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:03:10 +0000 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373A01eb010084; Thu, 3 Aug 2023 15:03:02 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=K5Mf4K28dVqGgOXG/25wlgXtHIWlnOLbNeyiTKRCs58=; b=R8 R90cjj8Imj+mZ5r3PGH6ve6znkyb7J9I/7mzr5gacwarmUe7Nb7+EWJpTNqAPjFe +NRAsMxWPu2YJjHGQ2jBm9IqyNuIyX5rxZ/+fo0R80nggyqgLATDYB/2aZGUsCiq nGjXrr0SwXd8i+wyIUNFnqfhqmOFYiObHP2mGPGtB+kC9vV/3oOarybnIWpaV6tN FyxTO3+zvHMnMxjSUjp7WCj3YCTjSydaGJhMJm0vQsoxvQ++ztPtHbXTmxuz4Mza uuX8b1yHxanLsTRQujyeboNgC5WWgKmR2Bk4Vo12YkQf6hTkTJDeh+cURE8Z5FTj HU3CUBHyKhPF1w6Vau4w== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s8a3qh1tn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:03:02 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 706F6100089; Thu, 3 Aug 2023 15:03:01 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 68CF82207B9; Thu, 3 Aug 2023 15:03:01 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:03:01 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 5/6] serial: stm32: replace access to DMAR bit by dmaengine_pause/resume Date: Thu, 3 Aug 2023 15:01:33 +0200 Message-ID: <20230803130134.155355-6-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060308_261131_54F41554 X-CRM114-Status: GOOD ( 24.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org It's rather advised to rely on DMA pause / resume instead of clearing/setting DMA request enable bit for the same purpose. Some DMA request/acknowledge race may encountered by doing so. We prefer to use dmaengine_pause and resume instead to pause a dma transfer when it is necessary. Create two new functions (stm32_usart_rx_dma_pause, stm32_usart_rx_dma _resume) to handle dma error when pausing/resuming. And rename stm32_usart_start_rx_dma_cyclic() to stm32_usart_rx_dma_start_or_resume() and use this function to resume an rx dma transfer. If resume fail, stm32_usart_rx_dma_start_or_resume can create a new transfer to continue. It is also safer to close DMA before reset DMAR in stm32_usart_shutdown. Signed-off-by: Valentin Caron --- drivers/tty/serial/stm32-usart.c | 200 ++++++++++++++++--------------- 1 file changed, 106 insertions(+), 94 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 0dae05a7abe6..8fc0526be898 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -326,6 +326,22 @@ static int stm32_usart_dma_pause_resume(struct stm32_port *stm32_port, return ret; } +static int stm32_usart_rx_dma_pause(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->rx_ch, + DMA_IN_PROGRESS, dmaengine_pause, + stm32_usart_rx_dma_started, + stm32_usart_rx_dma_terminate); +} + +static int stm32_usart_rx_dma_resume(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->rx_ch, + DMA_PAUSED, dmaengine_resume, + stm32_usart_rx_dma_started, + stm32_usart_rx_dma_terminate); +} + /* Return true when data is pending (in pio mode), and false when no data is pending. */ static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr) { @@ -485,7 +501,8 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, stm32_port->rx_ch->cookie, &stm32_port->rx_dma_state); - if (rx_dma_status == DMA_IN_PROGRESS) { + if (rx_dma_status == DMA_IN_PROGRESS || + rx_dma_status == DMA_PAUSED) { /* Empty DMA buffer */ size = stm32_usart_receive_chars_dma(port); sr = readl_relaxed(port->membase + ofs->isr); @@ -502,7 +519,6 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force } else { /* Disable RX DMA */ stm32_usart_rx_dma_terminate(stm32_port); - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); /* Fall back to interrupt mode */ dev_dbg(port->dev, "DMA error, fallback to irq mode\n"); size = stm32_usart_receive_chars_pio(port); @@ -514,6 +530,76 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force return size; } +static void stm32_usart_rx_dma_complete(void *arg) +{ + struct uart_port *port = arg; + struct tty_port *tport = &port->state->port; + unsigned int size; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq_irqrestore(port, flags); + if (size) + tty_flip_buffer_push(tport); +} + +static int stm32_usart_rx_dma_start_or_resume(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + struct dma_async_tx_descriptor *desc; + enum dma_status rx_dma_status; + int ret; + + if (stm32_port->throttled) + return 0; + + if (stm32_port->rx_dma_busy) { + rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, + stm32_port->rx_ch->cookie, + NULL); + if (rx_dma_status == DMA_IN_PROGRESS) + return 0; + + if (rx_dma_status == DMA_PAUSED && !stm32_usart_rx_dma_resume(stm32_port)) + return 0; + + dev_err(port->dev, "DMA failed : status error.\n"); + stm32_usart_rx_dma_terminate(stm32_port); + } + + stm32_port->rx_dma_busy = true; + + stm32_port->last_res = RX_BUF_L; + /* Prepare a DMA cyclic transaction */ + desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch, + stm32_port->rx_dma_buf, + RX_BUF_L, RX_BUF_P, + DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(port->dev, "rx dma prep cyclic failed\n"); + stm32_port->rx_dma_busy = false; + return -ENODEV; + } + + desc->callback = stm32_usart_rx_dma_complete; + desc->callback_param = port; + + /* Push current DMA transaction in the pending queue */ + ret = dma_submit_error(dmaengine_submit(desc)); + if (ret) { + dmaengine_terminate_sync(stm32_port->rx_ch); + stm32_port->rx_dma_busy = false; + return ret; + } + + /* Issue pending DMA requests */ + dma_async_issue_pending(stm32_port->rx_ch); + + return 0; +} + static void stm32_usart_tx_dma_terminate(struct stm32_port *stm32_port) { dmaengine_terminate_async(stm32_port->tx_ch); @@ -585,20 +671,6 @@ static void stm32_usart_tc_interrupt_enable(struct uart_port *port) stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE); } -static void stm32_usart_rx_dma_complete(void *arg) -{ - struct uart_port *port = arg; - struct tty_port *tport = &port->state->port; - unsigned int size; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - size = stm32_usart_receive_chars(port, false); - uart_unlock_and_check_sysrq_irqrestore(port, flags); - if (size) - tty_flip_buffer_push(tport); -} - static void stm32_usart_tx_interrupt_disable(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -924,11 +996,10 @@ static void stm32_usart_throttle(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* - * Disable DMA request line if enabled, so the RX data gets queued into the FIFO. + * Pause DMA transfer, so the RX data gets queued into the FIFO. * Hardware flow control is triggered when RX FIFO is full. */ - if (stm32_usart_rx_dma_started(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_pause(stm32_port); stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); if (stm32_port->cr3_irq) @@ -950,14 +1021,15 @@ static void stm32_usart_unthrottle(struct uart_port *port) if (stm32_port->cr3_irq) stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); + stm32_port->throttled = false; + /* - * Switch back to DMA mode (re-enable DMA request line). + * Switch back to DMA mode (resume DMA). * Hardware flow control is stopped when FIFO is not full any more. */ if (stm32_port->rx_ch) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_start_or_resume(port); - stm32_port->throttled = false; spin_unlock_irqrestore(&port->lock, flags); } @@ -968,8 +1040,7 @@ static void stm32_usart_stop_rx(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; /* Disable DMA request line. */ - if (stm32_port->rx_ch) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_pause(stm32_port); stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); if (stm32_port->cr3_irq) @@ -981,64 +1052,6 @@ static void stm32_usart_break_ctl(struct uart_port *port, int break_state) { } -static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) -{ - struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct dma_async_tx_descriptor *desc; - enum dma_status rx_dma_status; - int ret; - - if (stm32_port->rx_dma_busy) { - rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, - stm32_port->rx_ch->cookie, - NULL); - if (rx_dma_status == DMA_IN_PROGRESS) - return 0; - - dev_err(port->dev, "DMA failed : status error.\n"); - stm32_usart_rx_dma_terminate(stm32_port); - } - - stm32_port->rx_dma_busy = true; - - stm32_port->last_res = RX_BUF_L; - /* Prepare a DMA cyclic transaction */ - desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch, - stm32_port->rx_dma_buf, - RX_BUF_L, RX_BUF_P, - DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT); - if (!desc) { - dev_err(port->dev, "rx dma prep cyclic failed\n"); - stm32_port->rx_dma_busy = false; - return -ENODEV; - } - - desc->callback = stm32_usart_rx_dma_complete; - desc->callback_param = port; - - /* Push current DMA transaction in the pending queue */ - ret = dma_submit_error(dmaengine_submit(desc)); - if (ret) { - dmaengine_terminate_sync(stm32_port->rx_ch); - stm32_port->rx_dma_busy = false; - return ret; - } - - /* Issue pending DMA requests */ - dma_async_issue_pending(stm32_port->rx_ch); - - /* - * DMA request line not re-enabled at resume when port is throttled. - * It will be re-enabled by unthrottle ops. - */ - if (!stm32_port->throttled) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); - - return 0; -} - static int stm32_usart_startup(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -1064,7 +1077,7 @@ static int stm32_usart_startup(struct uart_port *port) writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr); if (stm32_port->rx_ch) { - ret = stm32_usart_start_rx_dma_cyclic(port); + ret = stm32_usart_rx_dma_start_or_resume(port); if (ret) { free_irq(port->irq, port); return ret; @@ -1811,11 +1824,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_PEIE); - cr3 = readl_relaxed(port->membase + ofs->cr3); - cr3 &= ~USART_CR3_EIE; - cr3 &= ~USART_CR3_DMAR; - cr3 &= ~USART_CR3_DDRE; - writel_relaxed(cr3, port->membase + ofs->cr3); if (stm32_port->tx_ch) { stm32_usart_of_dma_tx_remove(stm32_port, pdev); @@ -1827,7 +1835,12 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) dma_release_channel(stm32_port->rx_ch); } - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + cr3 = readl_relaxed(port->membase + ofs->cr3); + cr3 &= ~USART_CR3_EIE; + cr3 &= ~USART_CR3_DMAR; + cr3 &= ~USART_CR3_DMAT; + cr3 &= ~USART_CR3_DDRE; + writel_relaxed(cr3, port->membase + ofs->cr3); if (stm32_port->wakeup_src) { dev_pm_clear_wake_irq(&pdev->dev); @@ -1999,7 +2012,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct tty_port *tport = &port->state->port; int ret; - unsigned int size; + unsigned int size = 0; unsigned long flags; if (!stm32_port->wakeup_src || !tty_port_initialized(tport)) @@ -2021,10 +2034,9 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, */ if (stm32_port->rx_ch) { spin_lock_irqsave(&port->lock, flags); - /* Avoid race with RX IRQ when DMAR is cleared */ - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); /* Poll data from DMA RX buffer if any */ - size = stm32_usart_receive_chars(port, true); + if (!stm32_usart_rx_dma_pause(stm32_port)) + size += stm32_usart_receive_chars(port, true); stm32_usart_rx_dma_terminate(stm32_port); uart_unlock_and_check_sysrq_irqrestore(port, flags); if (size) @@ -2035,7 +2047,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, stm32_usart_receive_chars(port, false); } else { if (stm32_port->rx_ch) { - ret = stm32_usart_start_rx_dma_cyclic(port); + ret = stm32_usart_rx_dma_start_or_resume(port); if (ret) return ret; } From patchwork Thu Aug 3 13:01:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Valentin Caron X-Patchwork-Id: 13339965 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D045C04A94 for ; Thu, 3 Aug 2023 13:03:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=zsCZZ29wx/SyysqLoMwBAR3VV5MfJxWnpsfvY27rxGI=; b=syNYxSLrk6VfD5 ZsW9fHzXPKNh0DaCqCHf/zKCCtqpyKdCODuiltmFJaZDi+6UdRy71lU+VKc2q0H4u6vBBvCbaIW1y txGzIMWjAALhSetGBBF6z2ykNK0uEl6hsKnvHu+XE3dTPMBFTxh7EeN7EVrnPWZujIY/VaOJwBY29 2f9U3PskhzakKQuXzXyDr9d6s+8APJTZjVMl9poXfqYGm2w2PKsoITznS/EwjVquwi43XXToHJBup xwL2gguFA+uLQPcyRXhqCa13nnRVUHVlvr0HrKzak/3p8e6FdNXEaimF0JULj66pspyqDk69nFlls ZCgJ8QVNHjk0KJl0DvDg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyz-008kAc-2c; Thu, 03 Aug 2023 13:03:13 +0000 Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRXyw-008k70-0r for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 13:03:11 +0000 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 373CeVra009018; Thu, 3 Aug 2023 15:03:02 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= selector1; bh=8u4d3LvlGUVXnqclczmcYRVp1j8VsBGa+/jN0gq0QF0=; b=qx te2mDKZaPpbobyPTxf0NdlqR2169gtOYY18MhJjhEjNZY6GEnwi8Z0s88d9612z+ OsFanHq7SWUNkvFf2pukLcghm7v8f07jfdTdZTFEg1ruwET0nUEzjjY5IFtEbEZZ GGIv2x236sUW5JBLLjkYbZMXq1I6BMp3Z1eQR1IVsSiCaZiXNjDcqP+6sv1HK+ZK 6fxFp4AIqdy3+duOaPrPam+5m45dd0WYPTDI9TFmfiGvQL5sQx5YH7nVgFlYdGY8 CixfIJlNMqiD9lMmm4X2YkivSLbbNGECCKoCum6f6OjyFRHdh7PNvNkFjo7mtT8E N8s2y9Rtqgy8iOcBmJew== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3s8cet04np-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Aug 2023 15:03:02 +0200 (MEST) Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 419B010008B; Thu, 3 Aug 2023 15:03:02 +0200 (CEST) Received: from Webmail-eu.st.com (shfdag1node1.st.com [10.75.129.69]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 389C62207B5; Thu, 3 Aug 2023 15:03:02 +0200 (CEST) Received: from localhost (10.201.20.168) by SHFDAG1NODE1.st.com (10.75.129.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 3 Aug 2023 15:03:01 +0200 From: Valentin Caron To: Greg Kroah-Hartman CC: Jiri Slaby , Alexandre Torgue , Amelie Delaunay , , , , , Valentin Caron Subject: [PATCH 6/6] serial: stm32: synchronize RX DMA channel in shutdown Date: Thu, 3 Aug 2023 15:01:34 +0200 Message-ID: <20230803130134.155355-7-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230803130134.155355-1-valentin.caron@foss.st.com> References: <20230803130134.155355-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.20.168] X-ClientProxiedBy: SHFCAS1NODE2.st.com (10.75.129.73) To SHFDAG1NODE1.st.com (10.75.129.69) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-03_12,2023-08-03_01,2023-05-22_02 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_060310_595514_E0045ED5 X-CRM114-Status: GOOD ( 13.65 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Amelie Delaunay In shutdown, RX DMA channel is terminated. If the DMA RX callback is scheduled but not yet executed, while a new RX DMA transfer is started, the callback can be executed, and then disturb the ongoing RX DMA transfer. To avoid such a case, call dmaengine_synchronize in shutdown, after the DMA RX channel is terminated. Signed-off-by: Amelie Delaunay --- drivers/tty/serial/stm32-usart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 8fc0526be898..5e9cf0c48813 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1123,8 +1123,10 @@ static void stm32_usart_shutdown(struct uart_port *port) dev_err(port->dev, "Transmission is not complete\n"); /* Disable RX DMA. */ - if (stm32_port->rx_ch) + if (stm32_port->rx_ch) { stm32_usart_rx_dma_terminate(stm32_port); + dmaengine_synchronize(stm32_port->rx_ch); + } /* flush RX & TX FIFO */ if (ofs->rqr != UNDEF_REG)