Received: by 10.192.165.156 with SMTP id m28csp1625688imm; Thu, 12 Apr 2018 00:10:07 -0700 (PDT) X-Google-Smtp-Source: AIpwx48QoSVOgqaNkRazsB1IGeT04v+MDWf3q0/YXcaOgZLAD69qfJCat/58aZFBOu9ga7YbXpLY X-Received: by 2002:a17:902:8d98:: with SMTP id v24-v6mr8416844plo.21.1523517007466; Thu, 12 Apr 2018 00:10:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523517007; cv=none; d=google.com; s=arc-20160816; b=B3PJWqaqewjFPP1heFklQIn5sDqHLfxoMu/1cylSPHLaJJikgVIJ8Rl5kkLdtVmPvL W2h7EUcMJWnabyGb3UpZxNMwYJnnFa/e3Xa/KKjNyzWcayMs77Wk0atbgpltuCw9ulEj vb1TX2LWJBb5Tin0FsOjB4ARaFCQgsEEfKgbSJI6qRjBOQZaFUyX0Y7040vcIBs4pfZV uXBXjTOIrGhcmI07LcXWO4GOSTGU+5md6EZQp0nqnyFALZE9d8VSTcXDw/PT351kBxF6 eXFC/G8KQAZXgBLIZt/AXL14DF+yTZ4XoWAxpM1SMoDR+HQDYwkT8/JXuXqxF0EuvJgP aXGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:message-id:references :in-reply-to:subject:cc:to:from:date:content-transfer-encoding :mime-version:dkim-signature:dkim-signature :arc-authentication-results; bh=Nuf5qYbRZuvyQVocFWr2TPCrWGxkV9XDNxHL95Lt67Y=; b=WWqZo2paKPCxwjZy9qphZ5IF4wJ7tfWsCXG7RXEyjHR9DTyrduw7tHZ4ibd0aaYoEE 1Uq1XoKeweWCparYIgxLVoP7NoiFhTS38vPkA1kK7GaY+c4IsTWCVDoFsBlYewEEyk5g X68TajLPMDNyJ81vEBY65ePbSlUJ3CkXHfA91aTPrOeWWfj84YyoFb5Fkw6Rlr7u/OfW XjOgkalqPxGsw9IkLiwIGOruufKivZ+luyjB2mMA7IDA82DOKd7vvXxgETgeGsi+Di2Y QrVgELybnvERAyqyAYBvMPQZJc74UvX//th9I1auTXt1YuS3KUbclnpiaEYIWFFRMUJx AjuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Et7ormSP; dkim=pass header.i=@codeaurora.org header.s=default header.b=XNvGxxh9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r16si1839722pgq.324.2018.04.12.00.09.30; Thu, 12 Apr 2018 00:10:07 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Et7ormSP; dkim=pass header.i=@codeaurora.org header.s=default header.b=XNvGxxh9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752794AbeDLHGp (ORCPT + 99 others); Thu, 12 Apr 2018 03:06:45 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:44076 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751948AbeDLHGo (ORCPT ); Thu, 12 Apr 2018 03:06:44 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id BC8C060F93; Thu, 12 Apr 2018 07:06:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1523516803; bh=JaWVzwYZ3ZGzuzr5pQE+lRqxwIb4Q+/9RrfbaodUUQk=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=Et7ormSPIhSpvGbYFXq0vG8tv2UrXZlTWgMt9nk6zBCNBLD4Jwp9Q1TQuRTtapvO4 ZdO3PLT7LIObwK/KJ7bm+S84MZOJyq3uJ0TqB89o744nn2ThfWOCR74z8OGeHAu46x lJuCFwP6ixNsnLTNs1TQJ1X4iLIHUzHcFBbewMtA= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from mail.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id 4441560807; Thu, 12 Apr 2018 07:06:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1523516802; bh=JaWVzwYZ3ZGzuzr5pQE+lRqxwIb4Q+/9RrfbaodUUQk=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=XNvGxxh9MbneBOvQGI2/v8irjQgdFf1ENaJ4R6nGMvVgtlqQy/IviVOWC8LQ8E/Vt Yl0Tr01+ZAtf7yQcxaOmEgZJbiCqPnL+GlGDi+KlfzakjpN+cMs0FbdxBqTZIVeCKB xcCcV+AgxhSsqOvT5WE8ygwSKE69fX+UsPPGnNLw= MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Date: Thu, 12 Apr 2018 12:36:42 +0530 From: Abhishek Sahu To: Miquel Raynal Cc: Boris Brezillon , Archit Taneja , Richard Weinberger , linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Marek Vasut , linux-mtd@lists.infradead.org, Cyrille Pitchen , Andy Gross , Brian Norris , David Woodhouse Subject: Re: [PATCH 8/9] mtd: nand: qcom: helper function for raw read In-Reply-To: <20180410114428.68d59c8d@xps13> References: <1522845745-6624-1-git-send-email-absahu@codeaurora.org> <1522845745-6624-9-git-send-email-absahu@codeaurora.org> <20180410114428.68d59c8d@xps13> Message-ID: X-Sender: absahu@codeaurora.org User-Agent: Roundcube Webmail/1.2.5 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2018-04-10 15:14, Miquel Raynal wrote: > Hi Abhishek, > > On Wed, 4 Apr 2018 18:12:24 +0530, Abhishek Sahu > wrote: > >> This patch does minor code reorganization for raw reads. >> Currently the raw read is required for complete page but for >> subsequent patches related with erased codeword bit flips >> detection, only few CW should be read. So, this patch adds >> helper function and introduces the read CW bitmask which >> specifies which CW reads are required in complete page. > > I am not sure this is the right approach for subpage reads. If the > controller supports it, you should just enable it in chip->options. > Thanks Miquel. It is internal to this file only. This patch makes one static helper function which provides the support to read subpages. >> >> Signed-off-by: Abhishek Sahu >> --- >> drivers/mtd/nand/qcom_nandc.c | 186 >> +++++++++++++++++++++++++----------------- >> 1 file changed, 110 insertions(+), 76 deletions(-) >> >> diff --git a/drivers/mtd/nand/qcom_nandc.c >> b/drivers/mtd/nand/qcom_nandc.c >> index 40c790e..f5d1fa4 100644 >> --- a/drivers/mtd/nand/qcom_nandc.c >> +++ b/drivers/mtd/nand/qcom_nandc.c >> @@ -1590,6 +1590,114 @@ static int check_flash_errors(struct >> qcom_nand_host *host, int cw_cnt) >> } >> >> /* >> + * Helper to perform the page raw read operation. The read_cw_mask >> will be >> + * used to specify the codewords for which the data should be read. >> The >> + * single page contains multiple CW. Sometime, only few CW data is >> required >> + * in complete page. Also, start address will be determined with >> + * this CW mask to skip unnecessary data copy from NAND flash device. >> Then, >> + * actual data copy from NAND controller to data buffer will be done >> only >> + * for the CWs which have the mask set. >> + */ >> +static int >> +nandc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, >> + u8 *data_buf, u8 *oob_buf, >> + int page, unsigned long read_cw_mask) >> +{ >> + struct qcom_nand_host *host = to_qcom_nand_host(chip); >> + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); >> + struct nand_ecc_ctrl *ecc = &chip->ecc; >> + int i, ret; >> + int read_loc, start_step, last_step; >> + >> + nand_read_page_op(chip, page, 0, NULL, 0); >> + >> + host->use_ecc = false; >> + start_step = ffs(read_cw_mask) - 1; >> + last_step = fls(read_cw_mask); >> + >> + clear_bam_transaction(nandc); >> + set_address(host, host->cw_size * start_step, page); >> + update_rw_regs(host, last_step - start_step, true); >> + config_nand_page_read(nandc); >> + >> + for (i = start_step; i < last_step; i++) { >> + int data_size1, data_size2, oob_size1, oob_size2; >> + int reg_off = FLASH_BUF_ACC; >> + >> + data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1); >> + oob_size1 = host->bbm_size; >> + >> + if (i == (ecc->steps - 1)) { >> + data_size2 = ecc->size - data_size1 - >> + ((ecc->steps - 1) << 2); >> + oob_size2 = (ecc->steps << 2) + host->ecc_bytes_hw + >> + host->spare_bytes; >> + } else { >> + data_size2 = host->cw_data - data_size1; >> + oob_size2 = host->ecc_bytes_hw + host->spare_bytes; >> + } >> + >> + /* >> + * Don't perform actual data copy from NAND controller to data >> + * buffer through DMA for this codeword >> + */ >> + if (!(read_cw_mask & BIT(i))) { >> + if (nandc->props->is_bam) >> + nandc_set_read_loc(nandc, 0, 0, 0, 1); >> + >> + config_nand_cw_read(nandc, false); >> + >> + data_buf += data_size1 + data_size2; >> + oob_buf += oob_size1 + oob_size2; >> + >> + continue; >> + } >> + >> + if (nandc->props->is_bam) { >> + read_loc = 0; >> + nandc_set_read_loc(nandc, 0, read_loc, data_size1, 0); >> + read_loc += data_size1; >> + >> + nandc_set_read_loc(nandc, 1, read_loc, oob_size1, 0); >> + read_loc += oob_size1; >> + >> + nandc_set_read_loc(nandc, 2, read_loc, data_size2, 0); >> + read_loc += data_size2; >> + >> + nandc_set_read_loc(nandc, 3, read_loc, oob_size2, 1); >> + } >> + >> + config_nand_cw_read(nandc, false); >> + >> + read_data_dma(nandc, reg_off, data_buf, data_size1, 0); >> + reg_off += data_size1; >> + data_buf += data_size1; >> + >> + read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0); >> + reg_off += oob_size1; >> + oob_buf += oob_size1; >> + >> + read_data_dma(nandc, reg_off, data_buf, data_size2, 0); >> + reg_off += data_size2; >> + data_buf += data_size2; >> + >> + read_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); >> + oob_buf += oob_size2; >> + } >> + >> + ret = submit_descs(nandc); >> + if (ret) >> + dev_err(nandc->dev, "failure to read raw page\n"); >> + >> + free_descs(nandc); >> + >> + if (!ret) >> + ret = check_flash_errors(host, last_step - start_step); >> + >> + return 0; >> +} >> + >> +/* >> * reads back status registers set by the controller to notify page >> read >> * errors. this is equivalent to what 'ecc->correct()' would do. >> */ >> @@ -1839,82 +1947,8 @@ static int qcom_nandc_read_page_raw(struct >> mtd_info *mtd, >> struct nand_chip *chip, uint8_t *buf, >> int oob_required, int page) >> { >> - struct qcom_nand_host *host = to_qcom_nand_host(chip); >> - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); >> - u8 *data_buf, *oob_buf; >> - struct nand_ecc_ctrl *ecc = &chip->ecc; >> - int i, ret; >> - int read_loc; >> - >> - nand_read_page_op(chip, page, 0, NULL, 0); >> - data_buf = buf; >> - oob_buf = chip->oob_poi; >> - >> - host->use_ecc = false; >> - >> - clear_bam_transaction(nandc); >> - update_rw_regs(host, ecc->steps, true); >> - config_nand_page_read(nandc); >> - >> - for (i = 0; i < ecc->steps; i++) { >> - int data_size1, data_size2, oob_size1, oob_size2; >> - int reg_off = FLASH_BUF_ACC; >> - >> - data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1); >> - oob_size1 = host->bbm_size; >> - >> - if (i == (ecc->steps - 1)) { >> - data_size2 = ecc->size - data_size1 - >> - ((ecc->steps - 1) << 2); >> - oob_size2 = (ecc->steps << 2) + host->ecc_bytes_hw + >> - host->spare_bytes; >> - } else { >> - data_size2 = host->cw_data - data_size1; >> - oob_size2 = host->ecc_bytes_hw + host->spare_bytes; >> - } >> - >> - if (nandc->props->is_bam) { >> - read_loc = 0; >> - nandc_set_read_loc(nandc, 0, read_loc, data_size1, 0); >> - read_loc += data_size1; >> - >> - nandc_set_read_loc(nandc, 1, read_loc, oob_size1, 0); >> - read_loc += oob_size1; >> - >> - nandc_set_read_loc(nandc, 2, read_loc, data_size2, 0); >> - read_loc += data_size2; >> - >> - nandc_set_read_loc(nandc, 3, read_loc, oob_size2, 1); >> - } >> - >> - config_nand_cw_read(nandc, false); >> - >> - read_data_dma(nandc, reg_off, data_buf, data_size1, 0); >> - reg_off += data_size1; >> - data_buf += data_size1; >> - >> - read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0); >> - reg_off += oob_size1; >> - oob_buf += oob_size1; >> - >> - read_data_dma(nandc, reg_off, data_buf, data_size2, 0); >> - reg_off += data_size2; >> - data_buf += data_size2; >> - >> - read_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); >> - oob_buf += oob_size2; >> - } >> - >> - ret = submit_descs(nandc); >> - if (ret) >> - dev_err(nandc->dev, "failure to read raw page\n"); >> - >> - free_descs(nandc); >> - >> - if (!ret) >> - ret = check_flash_errors(host, ecc->steps); >> - >> - return 0; >> + return nandc_read_page_raw(mtd, chip, buf, chip->oob_poi, page, >> + BIT(chip->ecc.steps) - 1); > > I don't understand this. chip->ecc.steps is constant, right? So you > always ask for the same subpage? We need to do raw read for subpages in which we got uncorrectable error in next patch for erased page bitflip detection. This patch does reorganization of raw read and moves common code in helper function nandc_read_page_raw. For nomral raw read, all the subpages will be read so BIT(chip->ecc.steps) - 1 is used for qcom_nandc_read_page_raw. While for erased page raw read, only those sub pages will be read for which the controller gives the uncorrectable error. Thanks, Abhishek > >> } >> >> /* implements ecc->read_oob() */