From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99E4FC04EBF for ; Mon, 23 Sep 2019 13:59:16 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 6B99A20835 for ; Mon, 23 Sep 2019 13:59:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="HH8gz0K2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6B99A20835 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=emlix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=7AHfyILESf1pXZT0EsJivhTGKR148GfrQu4hkNIILJs=; b=HH8gz0K2QZcvca N7LPRTnL0Piz0TLEZbhyWTmXwS3+AqO0lp6Z2GgywJIeFwoOo7HzfycNSD8YNOstfCTW4tDOyfZfm Xhx7hMAEH+XXru43aL4mbu3WdNZ3RRhLnKsWuAabOdDrCugEihWlezbIPfUGn1qK5F8ylFGT0YYPJ ak8mBYX1RXd6Ul+TVmvUOuSn1xhyzvIIsUvp4Koi1qQBcZF1ecBs2d4oYTVHnW20eMMwstGZVQEPE TFdQEN5VGBcFmHEBR8xHECScK4hBii4XlB2Uio8ycYQmaeZUuz/9+QVqhDei0ard/lBhqp6rcbKOg 9MslJA6MVQgb9WbDJGhA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.2 #3 (Red Hat Linux)) id 1iCOrt-0006Lv-O9; Mon, 23 Sep 2019 13:59:09 +0000 Received: from mx1.emlix.com ([188.40.240.192]) by bombadil.infradead.org with esmtps (Exim 4.92.2 #3 (Red Hat Linux)) id 1iCOr5-0005Xm-6b for linux-arm-kernel@lists.infradead.org; Mon, 23 Sep 2019 13:58:22 +0000 Received: from mailer.emlix.com (unknown [81.20.119.6]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.emlix.com (Postfix) with ESMTPS id 451475FBA6; Mon, 23 Sep 2019 15:58:14 +0200 (CEST) From: Philipp Puschmann To: linux-kernel@vger.kernel.org Subject: [PATCH v5 2/3] dmaengine: imx-sdma: fix dma freezes Date: Mon, 23 Sep 2019 15:58:07 +0200 Message-Id: <20190923135808.815-3-philipp.puschmann@emlix.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190923135808.815-1-philipp.puschmann@emlix.com> References: <20190923135808.815-1-philipp.puschmann@emlix.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190923_065819_561859_E7E2950A X-CRM114-Status: GOOD ( 18.12 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fugang.duan@nxp.com, jlu@pengutronix.de, festevam@gmail.com, s.hauer@pengutronix.de, vkoul@kernel.org, linux-imx@nxp.com, kernel@pengutronix.de, dmaengine@vger.kernel.org, dan.j.williams@intel.com, yibin.gong@nxp.com, shawnguo@kernel.org, Philipp Puschmann , linux-arm-kernel@lists.infradead.org, l.stach@pengutronix.de Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org For some years and since many kernel versions there are reports that the RX UART SDMA channel stops working at some point. The workaround was to disable DMA for RX. This commit fixes the problem itself. Cyclic DMA transfers are used by uart and other drivers and these can fail in at least two cases where we can run out of descriptors available to the engine: - Interrupts are disabled for too long and all buffers are filled with data, especially in a setup where many small dma transfers are being executed only using a tiny part of a single buffer - DMA errors (such as generated by baud rate mismatch with imx-uart) use up all descriptors before we can react. In this case, SDMA stops the channel and no further transfers are done until the respective channel is disabled and re-enabled. We can check if the channel has been stopped and re-enable it then. To distinguish from the the case that the channel was stopped by upper-level driver we introduce new flag IMX_DMA_ACTIVE. As sdmac->desc is constant we can move desc out of the loop. Fixes: 1ec1e82f2510 ("dmaengine: Add Freescale i.MX SDMA support") Signed-off-by: Philipp Puschmann Signed-off-by: Jan Luebbe Reviewed-by: Lucas Stach --- Changelog v5: - join with patch version from Jan Luebbe - adapt comments and patch descriptions Changelog v4: - fixed the fixes tag Changelog v3: - use correct dma_wmb() instead of dma_wb() - add fixes tag Changelog v2: - clarify comment and commit description drivers/dma/imx-sdma.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index b42281604e54..0b1d6a62423d 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -383,6 +383,7 @@ struct sdma_channel { }; #define IMX_DMA_SG_LOOP BIT(0) +#define IMX_DMA_ACTIVE BIT(1) #define MAX_DMA_CHANNELS 32 #define MXC_SDMA_DEFAULT_PRIORITY 1 @@ -658,6 +659,9 @@ static int sdma_config_ownership(struct sdma_channel *sdmac, static void sdma_enable_channel(struct sdma_engine *sdma, int channel) { + struct sdma_channel *sdmac = &sdma->channel[channel]; + + sdmac->flags |= IMX_DMA_ACTIVE; writel(BIT(channel), sdma->regs + SDMA_H_START); } @@ -774,16 +778,17 @@ static void sdma_start_desc(struct sdma_channel *sdmac) static void sdma_update_channel_loop(struct sdma_channel *sdmac) { + struct sdma_engine *sdma = sdmac->sdma; struct sdma_buffer_descriptor *bd; + struct sdma_desc *desc = sdmac->desc; int error = 0; - enum dma_status old_status = sdmac->status; + enum dma_status old_status = sdmac->status; /* * loop mode. Iterate over descriptors, re-setup them and * call callback function. */ - while (sdmac->desc) { - struct sdma_desc *desc = sdmac->desc; + while (desc) { bd = &desc->bd[desc->buf_tail]; @@ -822,6 +827,18 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) if (error) sdmac->status = old_status; } + + /* In some situations it may happen that the sdma does not find any + * usable descriptor in the ring to put data into. The channel is + * stopped then and after having freed some buffers we have to restart + * it manually. + */ + if ((sdmac->flags & IMX_DMA_ACTIVE) && + !(readl_relaxed(sdma->regs + SDMA_H_STATSTOP) & BIT(sdmac->channel))) { + dev_err_ratelimited(sdma->dev, "SDMA channel %d: cyclic transfer disabled by HW, reenabling\n", + sdmac->channel); + writel(BIT(sdmac->channel), sdma->regs + SDMA_H_START); + }; } static void mxc_sdma_handle_channel_normal(struct sdma_channel *data) @@ -1051,7 +1068,8 @@ static int sdma_disable_channel(struct dma_chan *chan) struct sdma_engine *sdma = sdmac->sdma; int channel = sdmac->channel; - writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP); + sdmac->flags &= ~IMX_DMA_ACTIVE; + writel(BIT(channel), sdma->regs + SDMA_H_STATSTOP); sdmac->status = DMA_ERROR; return 0; -- 2.23.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel