From patchwork Thu Nov 29 15:45:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 10704781 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C468617D5 for ; Thu, 29 Nov 2018 15:45:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B2C2D2EF63 for ; Thu, 29 Nov 2018 15:45:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A6D0B2EFCF; Thu, 29 Nov 2018 15:45:28 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F0E4B2EF63 for ; Thu, 29 Nov 2018 15:45:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728921AbeK3CvO (ORCPT ); Thu, 29 Nov 2018 21:51:14 -0500 Received: from mailout2.hostsharing.net ([83.223.90.233]:44335 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728363AbeK3CvO (ORCPT ); Thu, 29 Nov 2018 21:51:14 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id DBD7310189B34; Thu, 29 Nov 2018 16:45:23 +0100 (CET) Received: from localhost (unknown [89.246.108.87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 8145B60171E8; Thu, 29 Nov 2018 16:45:23 +0100 (CET) X-Mailbox-Line: From 110014be1385cf8b3ee599d87f97774f3f05ac2f Mon Sep 17 00:00:00 2001 Message-Id: <110014be1385cf8b3ee599d87f97774f3f05ac2f.1543505321.git.lukas@wunner.de> From: Lukas Wunner Date: Thu, 29 Nov 2018 16:45:24 +0100 Subject: [PATCH for-4.21 1/3] spi: bcm2835: Polish transfer of DMA prologue MIME-Version: 1.0 To: Mark Brown Cc: Eric Anholt , Stefan Wahren , Frank Pavlic , Martin Sperl , Noralf Tronnes , linux-spi@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Commit 3bd7f6589f67 ("spi: bcm2835: Overcome sglist entry length limitation") was unfortunately merged even though submission of a refined version was imminent. Apply those refinements as an amendment: * Drop no longer needed #include . The lines requiring its inclusion were removed by the commit. * Change type of tx_spillover flag from bool to unsigned int for consistency with dma_pending flag and pursuant to Linus' dictum: https://lkml.org/lkml/2017/11/21/384 * In bcm2835_rd_fifo_count() do not check for bs->rx_buf != NULL. The function will never be called if that's the case. * Amend kerneldoc of bcm2835_wait_tx_fifo_empty() to prevent its use in situations where the function might spin forever. (In response to a review comment by Stefan Wahren.) * Sync only the cacheline containing the RX prologue back to memory, not the full first sglist entry. * Use sg_dma_address() and sg_dma_len() instead of referencing the sglist entry members directly. Seems to be the more common syntax in the tree, even for lvalues. Signed-off-by: Lukas Wunner Cc: Frank Pavlic Cc: Martin Sperl Cc: Noralf Trønnes --- drivers/spi/spi-bcm2835.c | 54 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 5cbdc94bb4cf..8c121b3374dd 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -20,7 +20,6 @@ * GNU General Public License for more details. */ -#include #include #include #include @@ -108,7 +107,7 @@ struct bcm2835_spi { int rx_len; int tx_prologue; int rx_prologue; - bool tx_spillover; + unsigned int tx_spillover; unsigned int dma_pending; }; @@ -155,21 +154,20 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) * The caller must ensure that @bs->rx_len is greater than or equal to @count, * that the RX FIFO contains at least @count bytes and that the DMA Enable flag * in the CS register is set (such that a read from the FIFO register receives - * 32-bit instead of just 8-bit). + * 32-bit instead of just 8-bit). Moreover @bs->rx_buf must not be %NULL. */ static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) { u32 val; + int len; bs->rx_len -= count; while (count > 0) { val = bcm2835_rd(bs, BCM2835_SPI_FIFO); - if (bs->rx_buf) { - int len = min(count, 4); - memcpy(bs->rx_buf, &val, len); - bs->rx_buf += len; - } + len = min(count, 4); + memcpy(bs->rx_buf, &val, len); + bs->rx_buf += len; count -= 4; } } @@ -187,12 +185,13 @@ static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) { u32 val; + int len; bs->tx_len -= count; while (count > 0) { if (bs->tx_buf) { - int len = min(count, 4); + len = min(count, 4); memcpy(&val, bs->tx_buf, len); bs->tx_buf += len; } else { @@ -206,6 +205,10 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) /** * bcm2835_wait_tx_fifo_empty() - busy-wait for TX FIFO to empty * @bs: BCM2835 SPI controller + * + * The caller must ensure that the RX FIFO can accommodate as many bytes + * as have been written to the TX FIFO: Transmission is halted once the + * RX FIFO is full, causing this function to spin forever. */ static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) { @@ -379,11 +382,12 @@ static void bcm2835_spi_transfer_prologue(struct spi_master *master, bcm2835_rd_fifo_count(bs, bs->rx_prologue); bcm2835_spi_reset_hw(master); - dma_sync_sg_for_device(master->dma_rx->device->dev, - tfr->rx_sg.sgl, 1, DMA_FROM_DEVICE); + dma_sync_single_for_device(master->dma_rx->device->dev, + sg_dma_address(&tfr->rx_sg.sgl[0]), + bs->rx_prologue, DMA_FROM_DEVICE); - tfr->rx_sg.sgl[0].dma_address += bs->rx_prologue; - tfr->rx_sg.sgl[0].length -= bs->rx_prologue; + sg_dma_address(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; + sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; } /* @@ -401,12 +405,12 @@ static void bcm2835_spi_transfer_prologue(struct spi_master *master, } if (likely(!bs->tx_spillover)) { - tfr->tx_sg.sgl[0].dma_address += bs->tx_prologue; - tfr->tx_sg.sgl[0].length -= bs->tx_prologue; + sg_dma_address(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; + sg_dma_len(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; } else { - tfr->tx_sg.sgl[0].length = 0; - tfr->tx_sg.sgl[1].dma_address += 4; - tfr->tx_sg.sgl[1].length -= 4; + sg_dma_len(&tfr->tx_sg.sgl[0]) = 0; + sg_dma_address(&tfr->tx_sg.sgl[1]) += 4; + sg_dma_len(&tfr->tx_sg.sgl[1]) -= 4; } } @@ -426,17 +430,17 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) return; if (bs->rx_prologue) { - tfr->rx_sg.sgl[0].dma_address -= bs->rx_prologue; - tfr->rx_sg.sgl[0].length += bs->rx_prologue; + sg_dma_address(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; + sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; } if (likely(!bs->tx_spillover)) { - tfr->tx_sg.sgl[0].dma_address -= bs->tx_prologue; - tfr->tx_sg.sgl[0].length += bs->tx_prologue; + sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; + sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; } else { - tfr->tx_sg.sgl[0].length = bs->tx_prologue - 4; - tfr->tx_sg.sgl[1].dma_address -= 4; - tfr->tx_sg.sgl[1].length += 4; + sg_dma_len(&tfr->tx_sg.sgl[0]) = bs->tx_prologue - 4; + sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; + sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; } } From patchwork Thu Nov 29 15:45:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 10704783 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 53EC9181D for ; Thu, 29 Nov 2018 15:46:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4223C2ED77 for ; Thu, 29 Nov 2018 15:46:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 357FC2F00E; Thu, 29 Nov 2018 15:46:53 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 02DE42EF66 for ; Thu, 29 Nov 2018 15:46:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728553AbeK3Cwi (ORCPT ); Thu, 29 Nov 2018 21:52:38 -0500 Received: from mailout3.hostsharing.net ([176.9.242.54]:43899 "EHLO mailout3.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728363AbeK3Cwi (ORCPT ); Thu, 29 Nov 2018 21:52:38 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout3.hostsharing.net (Postfix) with ESMTPS id 61DF8101E694B; Thu, 29 Nov 2018 16:46:47 +0100 (CET) Received: from localhost (unknown [89.246.108.87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id F1F3960171E8; Thu, 29 Nov 2018 16:46:46 +0100 (CET) X-Mailbox-Line: From ffff6fa349aa81fdce6da00e708ae111711bed21 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <110014be1385cf8b3ee599d87f97774f3f05ac2f.1543505321.git.lukas@wunner.de> References: <110014be1385cf8b3ee599d87f97774f3f05ac2f.1543505321.git.lukas@wunner.de> From: Lukas Wunner Date: Thu, 29 Nov 2018 16:45:24 +0100 Subject: [PATCH for-4.21 2/3] spi: bcm2835: Speed up FIFO access if fill level is known MIME-Version: 1.0 To: Mark Brown Cc: Eric Anholt , Stefan Wahren , Frank Pavlic , Martin Sperl , Noralf Tronnes , linux-spi@vger.kernel.org, linux-rpi-kernel@lists.infradead.org Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The RX and TX FIFO of the BCM2835 SPI master each accommodate 64 bytes (16 32-bit dwords). The CS register provides hints on their fill level: "Bit 19 RXR - RX FIFO needs Reading ([¾] full) 0 = RX FIFO is less than [¾] full (or not active TA = 0). 1 = RX FIFO is [¾] or more full. Cleared by reading sufficient data from the RX FIFO or setting TA to 0." "Bit 16 DONE - Transfer Done 0 = Transfer is in progress (or not active TA = 0). 1 = Transfer is complete. Cleared by writing more data to the TX FIFO or setting TA to 0." "If DONE is set [...], write up to 16 [dwords] to SPI_FIFO. [...] If RXR is set read 12 [dwords] data from SPI_FIFO." [Source: Pages 153, 154 and 158 of https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf Note: The spec is missing the "¾" character, presumably due to copy-pasting from a different charset. It also incorrectly refers to 16 and 12 "bytes" instead of 32-bit dwords.] In short, the RXR bit indicates that 48 bytes can be read and the DONE bit indicates 64 bytes can be written. Leverage this knowledge to read or write bytes blindly to the FIFO, without polling whether data can be read or free space is available to write. Moreover, when a transfer is starting, the TX FIFO is known to be empty, likewise allowing a blind write of 64 bytes. This cuts the number of bus accesses in half if the fill level is known. Also, the (posted) write accesses can be pipelined on the AXI bus since they are no longer interleaved with (non-posted) reads. bcm2835_spi_transfer_one_poll() switches to interrupt mode when a time limit is exceeded by calling bcm2835_spi_transfer_one_irq(). The TX FIFO may contain data in this case, but is known to be empty when the function is called from bcm2835_spi_transfer_one(). Hence only blindly fill the TX FIFO in the latter case but not the former. Signed-off-by: Lukas Wunner Tested-by: Eric Anholt Cc: Frank Pavlic Cc: Martin Sperl Cc: Noralf Trønnes --- Only change since v1: Call bcm2835_spi_transfer_one_irq() when falling back from poll mode to interrupt mode instead of open coding the same. (Martin Sperl) drivers/spi/spi-bcm2835.c | 64 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 8c121b3374dd..5af4cf74392c 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -71,6 +71,8 @@ #define BCM2835_SPI_CS_CS_10 0x00000002 #define BCM2835_SPI_CS_CS_01 0x00000001 +#define BCM2835_SPI_FIFO_SIZE 64 +#define BCM2835_SPI_FIFO_SIZE_3_4 48 #define BCM2835_SPI_POLLING_LIMIT_US 30 #define BCM2835_SPI_POLLING_JIFFIES 2 #define BCM2835_SPI_DMA_MIN_LENGTH 96 @@ -216,6 +218,45 @@ static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) cpu_relax(); } +/** + * bcm2835_rd_fifo_blind() - blindly read up to @count bytes from RX FIFO + * @bs: BCM2835 SPI controller + * @count: bytes available for reading in RX FIFO + */ +static inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count) +{ + u8 val; + + count = min(count, bs->rx_len); + bs->rx_len -= count; + + while (count) { + val = bcm2835_rd(bs, BCM2835_SPI_FIFO); + if (bs->rx_buf) + *bs->rx_buf++ = val; + count--; + } +} + +/** + * bcm2835_wr_fifo_blind() - blindly write up to @count bytes to TX FIFO + * @bs: BCM2835 SPI controller + * @count: bytes available for writing in TX FIFO + */ +static inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count) +{ + u8 val; + + count = min(count, bs->tx_len); + bs->tx_len -= count; + + while (count) { + val = bs->tx_buf ? *bs->tx_buf++ : 0; + bcm2835_wr(bs, BCM2835_SPI_FIFO, val); + count--; + } +} + static void bcm2835_spi_reset_hw(struct spi_master *master) { struct bcm2835_spi *bs = spi_master_get_devdata(master); @@ -239,6 +280,19 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) { struct spi_master *master = dev_id; struct bcm2835_spi *bs = spi_master_get_devdata(master); + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + + /* + * An interrupt is signaled either if DONE is set (TX FIFO empty) + * or if RXR is set (RX FIFO >= ¾ full). + */ + if (cs & BCM2835_SPI_CS_RXF) + bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); + else if (cs & BCM2835_SPI_CS_RXR) + bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE_3_4); + + if (bs->tx_len && cs & BCM2835_SPI_CS_DONE) + bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); /* Read as many bytes as possible from FIFO */ bcm2835_rd_fifo(bs); @@ -258,7 +312,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) static int bcm2835_spi_transfer_one_irq(struct spi_master *master, struct spi_device *spi, struct spi_transfer *tfr, - u32 cs) + u32 cs, bool fifo_empty) { struct bcm2835_spi *bs = spi_master_get_devdata(master); @@ -269,6 +323,8 @@ static int bcm2835_spi_transfer_one_irq(struct spi_master *master, bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); /* fill TX FIFO as much as possible */ + if (fifo_empty) + bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); bcm2835_wr_fifo(bs); /* enable interrupts */ @@ -682,7 +738,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, * if we are interrupted here, then the data is * getting transferred by the HW while we are interrupted */ - bcm2835_wr_fifo(bs); + bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); /* set the timeout */ timeout = jiffies + BCM2835_SPI_POLLING_JIFFIES; @@ -705,7 +761,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, bs->tx_len, bs->rx_len); /* fall back to interrupt mode */ return bcm2835_spi_transfer_one_irq(master, spi, - tfr, cs); + tfr, cs, false); } } @@ -779,7 +835,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, return bcm2835_spi_transfer_one_dma(master, spi, tfr, cs); /* run in interrupt-mode */ - return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); + return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs, true); } static int bcm2835_spi_prepare_message(struct spi_master *master, From patchwork Thu Nov 29 15:45:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 10704785 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 562A913AD for ; Thu, 29 Nov 2018 15:48:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F7392D1AF for ; Thu, 29 Nov 2018 15:48:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B3D32BD60; Thu, 29 Nov 2018 15:48:39 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CFC742B55C for ; Thu, 29 Nov 2018 15:48:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728363AbeK3CyY (ORCPT ); Thu, 29 Nov 2018 21:54:24 -0500 Received: from mailout2.hostsharing.net ([83.223.90.233]:47793 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728272AbeK3CyY (ORCPT ); Thu, 29 Nov 2018 21:54:24 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id 7430E10189B34; Thu, 29 Nov 2018 16:48:34 +0100 (CET) Received: from localhost (unknown [89.246.108.87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 1F3C160171E8; Thu, 29 Nov 2018 16:48:34 +0100 (CET) X-Mailbox-Line: From 16337812c5f93fe69456596a010c18f0117440ca Mon Sep 17 00:00:00 2001 Message-Id: <16337812c5f93fe69456596a010c18f0117440ca.1543505321.git.lukas@wunner.de> In-Reply-To: <110014be1385cf8b3ee599d87f97774f3f05ac2f.1543505321.git.lukas@wunner.de> References: <110014be1385cf8b3ee599d87f97774f3f05ac2f.1543505321.git.lukas@wunner.de> From: Lukas Wunner Date: Thu, 29 Nov 2018 16:45:24 +0100 Subject: [PATCH for-4.21 3/3] spi: bcm2835: Synchronize with callback on DMA termination MIME-Version: 1.0 To: Mark Brown Cc: Eric Anholt , Stefan Wahren , Frank Pavlic , Martin Sperl , Noralf Tronnes , linux-spi@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, Vinod Koul Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Commit b36f09c3c441 ("dmaengine: Add transfer termination synchronization support") deprecated dmaengine_terminate_all() in favor of dmaengine_terminate_sync() and dmaengine_terminate_async() to avoid freeing resources used by the DMA callback before its execution has concluded. Commit de92436ac40f ("dmaengine: bcm2835-dma: Use vchan_terminate_vdesc() instead of desc_free") amended the BCM2835 DMA driver with an implementation of ->device_synchronize(), which is a prerequisite for dmaengine_terminate_sync(). Thus, clients of the DMA driver (such as the BCM2835 SPI driver) may now be converted to the new API. It is generally desirable to use the _sync() variant except in atomic context. There is only a single occurrence where the BCM2835 SPI driver calls dmaengine_terminate_all() in atomic context and that is in bcm2835_spi_dma_done() (the RX DMA channel's callback) to terminate the TX DMA channel. The TX DMA channel doesn't have a callback (yet), hence it is safe to use the _async() variant there. Signed-off-by: Lukas Wunner Cc: Frank Pavlic Cc: Martin Sperl Cc: Noralf Trønnes Cc: Vinod Koul --- drivers/spi/spi-bcm2835.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 5af4cf74392c..35aebdfd3b4e 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -514,7 +514,7 @@ static void bcm2835_spi_dma_done(void *data) * situation otherwise... */ if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_all(master->dma_tx); + dmaengine_terminate_async(master->dma_tx); bcm2835_spi_undo_prologue(bs); } @@ -605,7 +605,7 @@ static int bcm2835_spi_transfer_one_dma(struct spi_master *master, ret = bcm2835_spi_prepare_sg(master, tfr, false); if (ret) { /* need to reset on errors */ - dmaengine_terminate_all(master->dma_tx); + dmaengine_terminate_sync(master->dma_tx); bs->dma_pending = false; goto err_reset_hw; } @@ -650,12 +650,12 @@ static bool bcm2835_spi_can_dma(struct spi_master *master, static void bcm2835_dma_release(struct spi_master *master) { if (master->dma_tx) { - dmaengine_terminate_all(master->dma_tx); + dmaengine_terminate_sync(master->dma_tx); dma_release_channel(master->dma_tx); master->dma_tx = NULL; } if (master->dma_rx) { - dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_sync(master->dma_rx); dma_release_channel(master->dma_rx); master->dma_rx = NULL; } @@ -864,8 +864,8 @@ static void bcm2835_spi_handle_err(struct spi_master *master, /* if an error occurred and we have an active dma, then terminate */ if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_all(master->dma_tx); - dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_sync(master->dma_tx); + dmaengine_terminate_sync(master->dma_rx); bcm2835_spi_undo_prologue(bs); } /* and reset */