Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp267720pxa; Wed, 5 Aug 2020 00:07:16 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxyW2JeaLrEYbyQOujJcwEGoFEUMdj404QPOje0+xpfm9j49Px3jjcv4hThXTgGVuqzMpHW X-Received: by 2002:a17:906:4acd:: with SMTP id u13mr1849802ejt.4.1596611236517; Wed, 05 Aug 2020 00:07:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596611236; cv=none; d=google.com; s=arc-20160816; b=unZcduQrUsmnuZG4OSMLeOIZ1fSn6kgIf5pzDy8QyKI+XwGqot4uDNq76HdQ6q+3wG EhkfG0RPOLz2+YQ1+ia9iAJz8o50l4/k770LrKcqMZlGlxglZT5HllNd1PigvEBjTBzN S1XnajiCgQz9RKMWN2wZsdW1QAvY74z5+x5suQF0iovDicy89UgDzjMg1sBub+fTtmKI +OuM9WVoPVZfQrUO4CwJI+V4A794sZ0DNCKvZdqaQpdtHfWZlnpLSPORkyBT0vHxYt9D 8xxdwaxN/5lkk4M/0013oBxYkdkF2vcqfuImklh2zVQ69d+QgnZ2tP+xo/pFFE+3juKg TgZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=6HEYx4CJ/TEY1W/3JDEab5AKC7WRGnQIhZXGA4yNhC0=; b=EyyOMZKHHFMp5Xor5W07CHv1Cq/U38ZPtQ2xHRRw+3W60yNOuQexM42YYjr0+1P2LZ 1vOZQp26RQfb+uGaip8kStF0Tu8SplPUkF80MobaT34j/7eKFHE9IwHAiRQa1TWE/bGC bYCePG4MBydNkqF3I2G8jmeZsYETLE5JimOKHJTvWK2k31fxvhTzuqNu73egNRBSDFO/ e8Ht3mrbtqUiV9fz4YthnLWt/e+glV172OC6mCe+nprESjD74UH2VVD6MLDPQDT6RXVC sUM1kKo0LSItLvjdFhgbhBo8XwWVRX1h6mdIqjSGte1G+CWQ8ifWw7IJN2auz3pNqs0L 5Y6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@st.com header.s=STMicroelectronics header.b=jeI2WxyS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=st.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e1si757900edn.361.2020.08.05.00.06.54; Wed, 05 Aug 2020 00:07:16 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@st.com header.s=STMicroelectronics header.b=jeI2WxyS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=st.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728573AbgHEHF2 (ORCPT + 99 others); Wed, 5 Aug 2020 03:05:28 -0400 Received: from mx07-00178001.pphosted.com ([185.132.182.106]:44409 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728315AbgHEHEd (ORCPT ); Wed, 5 Aug 2020 03:04:33 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 07573JAQ012732; Wed, 5 Aug 2020 09:04:19 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=STMicroelectronics; bh=6HEYx4CJ/TEY1W/3JDEab5AKC7WRGnQIhZXGA4yNhC0=; b=jeI2WxySP3nimvauzE/ZjBZMbjSgxw67skG8jm50trh2oUd2adGA5A+ggwIJ+00Bcuol 7xNVfiaUFE8kQG2/UAVymMVFiVl1Xj6Md8WIDj/myG21j23MsmkDpcu8pSqwguvn3V0+ 8wvv4iuWG+FIMOJzrTExnCCH/41QW0C32Lt+mVcAzODLSkDV3Ey8f9pWkN4n4jhAOWm+ e7Y1dO+pJXlXpWREWeY3kF+hEF41T3y7quBa9TiU7jVk7hv54v+VaWVcGklr+PliTMfl g3MCt4+ck0TdpdrFKSv+6mqbeFNDryUD9O+ZgyFAwBvhJprc2rfYGPi0+WLWSwVXh2DN jw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 32n6theqj2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 05 Aug 2020 09:04:19 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id E44FB100034; Wed, 5 Aug 2020 09:04:18 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag3node2.st.com [10.75.127.8]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id D82A42A4D8E; Wed, 5 Aug 2020 09:04:18 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG3NODE2.st.com (10.75.127.8) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Wed, 5 Aug 2020 09:04:18 +0200 From: Alain Volmat To: , CC: , , , , , , , Subject: [PATCH 13/18] spi: stm32h7: fix handling of dma transfer completed Date: Wed, 5 Aug 2020 09:02:08 +0200 Message-ID: <1596610933-32599-14-git-send-email-alain.volmat@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1596610933-32599-1-git-send-email-alain.volmat@st.com> References: <1596610933-32599-1-git-send-email-alain.volmat@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG8NODE3.st.com (10.75.127.24) To SFHDAG3NODE2.st.com (10.75.127.8) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235,18.0.687 definitions=2020-08-05_04:2020-08-03,2020-08-05 signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Amelie Delaunay The rx dma is completed "after" the last data is received from spi. Thus, to avoid loss of rx data, it's mandatory to wait for the dma callback before tearing down the rx dma in stm32_spi_disable(). The tx dma is of course already completed when last data is sent from spi. But both spi and dma use threaded interrupts, thus there is no guarantee that the dma irq handler is already executed when the spi irq handler triggers stm32_spi_disable(). Waiting for dma callback will allow a clean termination of the dma. Remove the unused code in the current dma callback, signal the end of dma through completion, then delay spi disable until the dma callback has been executed. Signed-off-by: Antonio Borneo Signed-off-by: Amelie Delaunay Signed-off-by: Alain Volmat --- drivers/spi/spi-stm32.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 1a703c4a65db..b0a9642392e9 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -275,6 +275,7 @@ struct stm32_spi_cfg { * @rx_len: number of data to be read in bytes * @dma_tx: dma channel for TX transfer * @dma_rx: dma channel for RX transfer + * @dma_completion: completion to wait for end of DMA transfer * @phys_addr: SPI registers physical base address * @xfer_completion: completion to wait for end of transfer * @xfer_status: current transfer status @@ -304,6 +305,7 @@ struct stm32_spi { int rx_len; struct dma_chan *dma_tx; struct dma_chan *dma_rx; + struct completion dma_completion; dma_addr_t phys_addr; struct completion xfer_completion; int xfer_status; @@ -1062,25 +1064,18 @@ static void stm32f4_spi_dma_rx_cb(void *data) * stm32h7_spi_dma_cb - dma callback * @data: pointer to the spi controller data structure * - * DMA callback is called when the transfer is complete or when an error - * occurs. If the transfer is complete, EOT flag is raised. + * DMA callback is called when the transfer is complete. */ static void stm32h7_spi_dma_cb(void *data) { struct stm32_spi *spi = data; unsigned long flags; - u32 sr; spin_lock_irqsave(&spi->lock, flags); - sr = readl_relaxed(spi->base + STM32H7_SPI_SR); + complete(&spi->dma_completion); spin_unlock_irqrestore(&spi->lock, flags); - - if (!(sr & STM32H7_SPI_SR_EOT)) - dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr); - - /* Now wait for EOT, or SUSP or OVR in case of error */ } /** @@ -1274,12 +1269,20 @@ static int stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, struct spi_transfer *xfer) { + dma_async_tx_callback rx_done = NULL, tx_done = NULL; struct dma_slave_config tx_dma_conf, rx_dma_conf; struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc; unsigned long flags; spin_lock_irqsave(&spi->lock, flags); + if (spi->rx_buf) + rx_done = spi->cfg->dma_rx_cb; + else if (spi->tx_buf) + tx_done = spi->cfg->dma_tx_cb; + + reinit_completion(&spi->dma_completion); + rx_dma_desc = NULL; if (spi->rx_buf && spi->dma_rx) { stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM); @@ -1316,7 +1319,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, goto dma_desc_error; if (rx_dma_desc) { - rx_dma_desc->callback = spi->cfg->dma_rx_cb; + rx_dma_desc->callback = rx_done; rx_dma_desc->callback_param = spi; if (dma_submit_error(dmaengine_submit(rx_dma_desc))) { @@ -1330,7 +1333,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, if (tx_dma_desc) { if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { - tx_dma_desc->callback = spi->cfg->dma_tx_cb; + tx_dma_desc->callback = tx_done; tx_dma_desc->callback_param = spi; } @@ -1658,6 +1661,7 @@ static int stm32_spi_transfer_one(struct spi_master *master, { struct stm32_spi *spi = spi_master_get_devdata(master); u32 xfer_time, midi_delay_ns; + unsigned long timeout; int ret; spi->tx_buf = transfer->tx_buf; @@ -1690,10 +1694,14 @@ static int stm32_spi_transfer_one(struct spi_master *master, midi_delay_ns = spi->cur_xferlen * 8 / spi->cur_bpw * spi->cur_midi; xfer_time += DIV_ROUND_UP(midi_delay_ns, NSEC_PER_MSEC); xfer_time = max(2 * xfer_time, 100U); + timeout = msecs_to_jiffies(xfer_time); + + timeout = wait_for_completion_timeout(&spi->xfer_completion, timeout); + if (timeout && spi->cur_usedma) + timeout = wait_for_completion_timeout(&spi->dma_completion, + timeout); - ret = wait_for_completion_timeout(&spi->xfer_completion, - (msecs_to_jiffies(xfer_time))); - if (!ret) { + if (!timeout) { dev_err(spi->dev, "SPI transfer timeout (%u ms)\n", xfer_time); spi->xfer_status = -ETIMEDOUT; } @@ -1854,6 +1862,7 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->master = master; spin_lock_init(&spi->lock); init_completion(&spi->xfer_completion); + init_completion(&spi->dma_completion); spi->cfg = (const struct stm32_spi_cfg *) of_match_device(pdev->dev.driver->of_match_table, -- 2.7.4