From patchwork Wed Apr 4 12:42:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhishek Sahu X-Patchwork-Id: 10322553 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C91F560318 for ; Wed, 4 Apr 2018 12:45:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B7B8528D54 for ; Wed, 4 Apr 2018 12:45:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AA18A28E76; Wed, 4 Apr 2018 12:45:08 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable 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 0F89628D54 for ; Wed, 4 Apr 2018 12:45:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751313AbeDDMm5 (ORCPT ); Wed, 4 Apr 2018 08:42:57 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:40554 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751038AbeDDMmy (ORCPT ); Wed, 4 Apr 2018 08:42:54 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E3DCF60F6B; Wed, 4 Apr 2018 12:42:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522845773; bh=4NXg57UtRP5eA9kjNmS+mo4ghDjq9IXsBBSbWksuSO8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WY8YPQz4TGzcMriWRphMLb68BvSJt8fBa3ntUO5WZ8Z7E4VexdeDXLBMZrSE65hmA ld1/Sk/UjQuED7XOajQpnZssM5VpydtBZQpv/PTyO/fIMrpHUdB0wDHYtHow98ryAa Hu2duvS91qVZmtA5o9PqFLWPYmWNuVNivTP/Loo8= Received: from absahu-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: absahu@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 1566960C55; Wed, 4 Apr 2018 12:42:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522845772; bh=4NXg57UtRP5eA9kjNmS+mo4ghDjq9IXsBBSbWksuSO8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LdCSWB2WL6ZKSpwKKl6JqJtwqUvztrvBg0qhkr5LCgX4cZLB1QY1bJ0+B3ffk/oUe WmmFkITRjOmgmuj5z4XwXke91q/SMKaH81UltNxJZ2ljXy12/zk4Zsxt/3c6LmRuih dzRVGQ4lScuxm5cwUGl7+qcCqNhIvJh1MvybfTmo= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 1566960C55 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=absahu@codeaurora.org From: Abhishek Sahu To: Boris Brezillon Cc: David Woodhouse , Brian Norris , Marek Vasut , Richard Weinberger , Cyrille Pitchen , linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, Andy Gross , Archit Taneja , Abhishek Sahu Subject: [PATCH 2/9] mtd: nand: qcom: wait for desc completion in all BAM channels Date: Wed, 4 Apr 2018 18:12:18 +0530 Message-Id: <1522845745-6624-3-git-send-email-absahu@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1522845745-6624-1-git-send-email-absahu@codeaurora.org> References: <1522845745-6624-1-git-send-email-absahu@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The BAM has 3 channels - tx, rx and command. command channel is used for register read/writes, tx channel for data writes and rx channel for data reads. Currently, the driver assumes the transfer completion once it gets all the command descriptor completed. Sometimes, there is race condition in data channel (tx/rx) and command channel completion and in these cases, the data in buffer is not valid during the small window between command descriptor completion and data descriptor completion. Now, the changes have been made to assign the callback for channel's final descriptor. The DMA will generate the callback when all the descriptor have completed in that channel. The NAND transfer will be completed only when all required DMA channels have generated the completion callback. Signed-off-by: Abhishek Sahu --- drivers/mtd/nand/qcom_nandc.c | 55 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index 8dd40de..17321fc 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -213,6 +213,8 @@ #define QPIC_PER_CW_CMD_SGL 32 #define QPIC_PER_CW_DATA_SGL 8 +#define QPIC_NAND_COMPLETION_TIMEOUT msecs_to_jiffies(2000) + /* * Flags used in DMA descriptor preparation helper functions * (i.e. read_reg_dma/write_reg_dma/read_data_dma/write_data_dma) @@ -245,6 +247,11 @@ * @tx_sgl_start - start index in data sgl for tx. * @rx_sgl_pos - current index in data sgl for rx. * @rx_sgl_start - start index in data sgl for rx. + * @first_chan_done - if current transfer already has got first channel + * DMA desc completion. + * @txn_done - completion for nand transfer. + * @last_data_desc - last DMA desc in data channel (tx/rx). + * @last_cmd_desc - last DMA desc in command channel. */ struct bam_transaction { struct bam_cmd_element *bam_ce; @@ -258,6 +265,10 @@ struct bam_transaction { u32 tx_sgl_start; u32 rx_sgl_pos; u32 rx_sgl_start; + bool first_chan_done; + struct completion txn_done; + struct dma_async_tx_descriptor *last_data_desc; + struct dma_async_tx_descriptor *last_cmd_desc; }; /* @@ -504,6 +515,8 @@ static void free_bam_transaction(struct qcom_nand_controller *nandc) bam_txn->data_sgl = bam_txn_buf; + init_completion(&bam_txn->txn_done); + return bam_txn; } @@ -523,11 +536,36 @@ static void clear_bam_transaction(struct qcom_nand_controller *nandc) bam_txn->tx_sgl_start = 0; bam_txn->rx_sgl_pos = 0; bam_txn->rx_sgl_start = 0; + bam_txn->last_data_desc = NULL; + bam_txn->first_chan_done = false; sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * QPIC_PER_CW_CMD_SGL); sg_init_table(bam_txn->data_sgl, nandc->max_cwperpage * QPIC_PER_CW_DATA_SGL); + + reinit_completion(&bam_txn->txn_done); +} + +/* Callback for DMA descriptor completion */ +static void qpic_bam_dma_done(void *data) +{ + struct bam_transaction *bam_txn = data; + + /* + * In case of data transfer with NAND, 2 callbacks will be generated. + * One for command channel and another one for data channel. + * If current transaction has data descriptors then check if its + * already got one DMA channel completion callback. In this case + * make the NAND transfer complete otherwise mark first_chan_done true + * and wait for next channel DMA completion callback. + */ + if (bam_txn->last_data_desc && !bam_txn->first_chan_done) { + bam_txn->first_chan_done = true; + return; + } + + complete(&bam_txn->txn_done); } static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) @@ -756,6 +794,12 @@ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc, desc->dma_desc = dma_desc; + /* update last data/command descriptor */ + if (chan == nandc->cmd_chan) + bam_txn->last_cmd_desc = dma_desc; + else + bam_txn->last_data_desc = dma_desc; + list_add_tail(&desc->node, &nandc->desc_list); return 0; @@ -1273,10 +1317,19 @@ static int submit_descs(struct qcom_nand_controller *nandc) cookie = dmaengine_submit(desc->dma_desc); if (nandc->props->is_bam) { + bam_txn->last_cmd_desc->callback = qpic_bam_dma_done; + bam_txn->last_cmd_desc->callback_param = bam_txn; + if (bam_txn->last_data_desc) { + bam_txn->last_data_desc->callback = qpic_bam_dma_done; + bam_txn->last_data_desc->callback_param = bam_txn; + } + dma_async_issue_pending(nandc->tx_chan); dma_async_issue_pending(nandc->rx_chan); + dma_async_issue_pending(nandc->cmd_chan); - if (dma_sync_wait(nandc->cmd_chan, cookie) != DMA_COMPLETE) + if (!wait_for_completion_timeout(&bam_txn->txn_done, + QPIC_NAND_COMPLETION_TIMEOUT)) return -ETIMEDOUT; } else { if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE)