From patchwork Wed Feb 24 08:20:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sascha Hauer X-Patchwork-Id: 8402661 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E436BC0553 for ; Wed, 24 Feb 2016 08:20:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F0D3A2034A for ; Wed, 24 Feb 2016 08:20:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 03388202EB for ; Wed, 24 Feb 2016 08:20:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757957AbcBXIU4 (ORCPT ); Wed, 24 Feb 2016 03:20:56 -0500 Received: from metis.ext.4.pengutronix.de ([92.198.50.35]:60432 "EHLO metis.ext.4.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757932AbcBXIUz (ORCPT ); Wed, 24 Feb 2016 03:20:55 -0500 Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1aYUgY-0004AE-9D; Wed, 24 Feb 2016 09:20:38 +0100 Received: from sha by dude.hi.pengutronix.de with local (Exim 4.86) (envelope-from ) id 1aYUgX-0002ab-Jz; Wed, 24 Feb 2016 09:20:37 +0100 From: Sascha Hauer To: linux-spi@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Mark Brown , Anton Bondarenko , Sascha Hauer Subject: [PATCH 9/9] spi: imx: drop bogus tests for rx/tx bufs in DMA transfer Date: Wed, 24 Feb 2016 09:20:33 +0100 Message-Id: <1456302033-25638-10-git-send-email-s.hauer@pengutronix.de> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1456302033-25638-1-git-send-email-s.hauer@pengutronix.de> References: <1456302033-25638-1-git-send-email-s.hauer@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: sha@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-spi@vger.kernel.org Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The driver tries to be clever by only setting up DMA channels when the corresponding sg tables are non NULL. The sg tables are embedded structs in struct spi_transfer, so they are guaranteed to be non NULL which makes the if(tx)/if(rx) tests completely bogus. The driver even sets the SPI_MASTER_MUST_RX / SPI_MASTER_MUST_TX flags which makes sure the sg tables are not only present but also non empty. Drop the tests and make the DMA path easier to follow. Signed-off-by: Sascha Hauer --- drivers/spi/spi-imx.c | 82 +++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 91890b2..e7a19be 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -974,51 +974,40 @@ static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size) static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, struct spi_transfer *transfer) { - struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; - int ret; + struct dma_async_tx_descriptor *desc_tx, *desc_rx; unsigned long transfer_timeout; unsigned long timeout; struct spi_master *master = spi_imx->bitbang.master; struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; - if (tx) { - desc_tx = dmaengine_prep_slave_sg(master->dma_tx, - tx->sgl, tx->nents, DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc_tx) - return -EINVAL; - - desc_tx->callback = spi_imx_dma_tx_callback; - desc_tx->callback_param = (void *)spi_imx; - dmaengine_submit(desc_tx); - } + /* + * The TX DMA setup starts the transfer, so make sure RX is configured + * before TX. + */ + desc_rx = dmaengine_prep_slave_sg(master->dma_rx, + rx->sgl, rx->nents, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_rx) + return -EINVAL; - if (rx) { - desc_rx = dmaengine_prep_slave_sg(master->dma_rx, - rx->sgl, rx->nents, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc_rx) { - dmaengine_terminate_all(master->dma_tx); - return -EINVAL; - } + desc_rx->callback = spi_imx_dma_rx_callback; + desc_rx->callback_param = (void *)spi_imx; + dmaengine_submit(desc_rx); + reinit_completion(&spi_imx->dma_rx_completion); + dma_async_issue_pending(master->dma_rx); - desc_rx->callback = spi_imx_dma_rx_callback; - desc_rx->callback_param = (void *)spi_imx; - dmaengine_submit(desc_rx); + desc_tx = dmaengine_prep_slave_sg(master->dma_tx, + tx->sgl, tx->nents, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_tx) { + dmaengine_terminate_all(master->dma_tx); + return -EINVAL; } - reinit_completion(&spi_imx->dma_rx_completion); + desc_tx->callback = spi_imx_dma_tx_callback; + desc_tx->callback_param = (void *)spi_imx; + dmaengine_submit(desc_tx); reinit_completion(&spi_imx->dma_tx_completion); - - /* - * Set these order to avoid potential RX overflow. The overflow may - * happen if we enable SPI HW before starting RX DMA due to rescheduling - * for another task and/or interrupt. - * So RX DMA enabled first to make sure data would be read out from FIFO - * ASAP. TX DMA enabled next to start filling TX FIFO with new data. - * And finaly SPI HW enabled to start actual data transfer. - */ - dma_async_issue_pending(master->dma_rx); dma_async_issue_pending(master->dma_tx); transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len); @@ -1030,22 +1019,19 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dev_err(spi_imx->dev, "I/O Error in DMA TX\n"); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); - } else { - timeout = wait_for_completion_timeout( - &spi_imx->dma_rx_completion, transfer_timeout); - if (!timeout) { - dev_err(spi_imx->dev, "I/O Error in DMA RX\n"); - spi_imx->devtype_data->reset(spi_imx); - dmaengine_terminate_all(master->dma_rx); - } + return -ETIMEDOUT; } - if (!timeout) - ret = -ETIMEDOUT; - else - ret = transfer->len; + timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion, + transfer_timeout); + if (!timeout) { + dev_err(&master->dev, "I/O Error in DMA RX\n"); + spi_imx->devtype_data->reset(spi_imx); + dmaengine_terminate_all(master->dma_rx); + return -ETIMEDOUT; + } - return ret; + return transfer->len; } static int spi_imx_pio_transfer(struct spi_device *spi,