From patchwork Mon Jan 13 06:27:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Huang Shijie X-Patchwork-Id: 3473771 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 506F0C02DC for ; Mon, 13 Jan 2014 07:03:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C084F2010E for ; Mon, 13 Jan 2014 07:03:55 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 53D74200FE for ; Mon, 13 Jan 2014 07:03:54 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W2bY5-0004HQ-OF; Mon, 13 Jan 2014 07:03:02 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1W2bY3-00069d-7w; Mon, 13 Jan 2014 07:02:59 +0000 Received: from co1ehsobe005.messaging.microsoft.com ([216.32.180.188] helo=co1outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W2bXz-00068x-F6; Mon, 13 Jan 2014 07:02:56 +0000 Received: from mail141-co1-R.bigfish.com (10.243.78.242) by CO1EHSOBE023.bigfish.com (10.243.66.86) with Microsoft SMTP Server id 14.1.225.22; Mon, 13 Jan 2014 07:02:27 +0000 Received: from mail141-co1 (localhost [127.0.0.1]) by mail141-co1-R.bigfish.com (Postfix) with ESMTP id D91AD1C03A5; Mon, 13 Jan 2014 07:02:26 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 6 X-BigFish: VS6(z3121kzzz1f42h2148h208ch1ee6h1de0h1fdah2073h2146h1202h1e76h2189h1d1ah1d2ah1fc6h1082kzz1de098h8275bh1de097hz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh2222h224fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h2327h2336h2438h2461h1155h) Received: from mail141-co1 (localhost.localdomain [127.0.0.1]) by mail141-co1 (MessageSwitch) id 1389596544844894_18981; Mon, 13 Jan 2014 07:02:24 +0000 (UTC) Received: from CO1EHSMHS028.bigfish.com (unknown [10.243.78.228]) by mail141-co1.bigfish.com (Postfix) with ESMTP id C7176400047; Mon, 13 Jan 2014 07:02:24 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CO1EHSMHS028.bigfish.com (10.243.66.38) with Microsoft SMTP Server (TLS) id 14.16.227.3; Mon, 13 Jan 2014 07:02:24 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-004.039d.mgd.msft.net (10.84.1.14) with Microsoft SMTP Server (TLS) id 14.3.158.2; Mon, 13 Jan 2014 07:02:23 +0000 Received: from shlinux2.ap.freescale.net (shlinux2.ap.freescale.net [10.192.224.44]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s0D72Gpk027301; Mon, 13 Jan 2014 00:02:21 -0700 From: Huang Shijie To: Subject: [PATCH fix] mtd: nand: kill the the NAND_MAX_PAGESIZE/NAND_MAX_OOBSIZE for nand_buffers{} Date: Mon, 13 Jan 2014 14:27:12 +0800 Message-ID: <1389594432-23482-1-git-send-email-b32955@freescale.com> X-Mailer: git-send-email 1.7.2.rc3 In-Reply-To: <20140111233937.GF1992@norris-Latitude-E6410> References: <20140111233937.GF1992@norris-Latitude-E6410> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-FOPE-CONNECTOR: Id%0$Dn%FREESCALE.MAIL.ONMICROSOFT.COM$RO%1$TLS%0$FQDN%$TlsDn% X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140113_020255_822607_386A2144 X-CRM114-Status: GOOD ( 20.79 ) X-Spam-Score: -1.3 (-) Cc: Huang Shijie , computersforpeace@gmail.com, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-3.1 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD,UNPARSEABLE_RELAY,UNRESOLVED_TEMPLATE autolearn=ham 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 patch converts the arrays to buffer pointers for nand_buffers{}. The cafe_nand.c is the only NAND_OWN_BUFFERS user which allocates a nand_buffers{} itself. This patch disables the DMA for nand_scan_ident, and restore the DMA status after we finish the nand_scan_ident. By this way, we can get the mtd->writesize and mtd->oobsize, and then allocates the cafe->dmabuf with them. Since the cafe_nand.c uses the NAND_ECC_HW_SYNDROME ECC mode, we do not allocate the buffers for @ecccalc and @ecccode. Signed-off-by: Huang Shijie --- fix: Setup the DMA address after we have allocated the DMA buffer. --- drivers/mtd/nand/cafe_nand.c | 68 ++++++++++++++++++++++++++++------------- drivers/mtd/nand/nand_base.c | 19 +++++++++-- include/linux/mtd/nand.h | 12 ++++---- 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index f2f64ad..4e66726 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, struct cafe_priv *cafe; uint32_t ctrl; int err = 0; + int old_dma; + struct nand_buffers *nbuf; /* Very old versions shared the same PCI ident for all three functions on the chip. Verify the class too... */ @@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, err = -ENOMEM; goto out_free_mtd; } - cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers), - &cafe->dmaaddr, GFP_KERNEL); - if (!cafe->dmabuf) { - err = -ENOMEM; - goto out_ior; - } - cafe->nand.buffers = (void *)cafe->dmabuf + 2112; cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); if (!cafe->rs) { @@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, "CAFE NAND", mtd); if (err) { dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); - goto out_free_dma; + goto out_ior; } /* Disable master reset, enable NAND clock */ @@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe_writel(cafe, 0x7006, GLOBAL_CTRL); cafe_writel(cafe, 0x700a, GLOBAL_CTRL); + /* Enable NAND IRQ in global IRQ mask register */ + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); + cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", + cafe_readl(cafe, GLOBAL_CTRL), + cafe_readl(cafe, GLOBAL_IRQ_MASK)); + + /* Do not use the DMA for the nand_scan_ident() */ + old_dma = usedma; + usedma = 0; + + /* Scan to find existence of the device */ + if (nand_scan_ident(mtd, 2, NULL)) { + err = -ENXIO; + goto out_irq; + } + + cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, + 2112 + sizeof(struct nand_buffers) + + mtd->writesize + mtd->oobsize, + &cafe->dmaaddr, GFP_KERNEL); + if (!cafe->dmabuf) { + err = -ENOMEM; + goto out_irq; + } + cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112; + /* Set up DMA address */ cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); if (sizeof(cafe->dmaaddr) > 4) @@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); - /* Enable NAND IRQ in global IRQ mask register */ - cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); - cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", - cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); + /* this driver does not need the @ecccalc and @ecccode */ + nbuf->ecccalc = NULL; + nbuf->ecccode = NULL; + nbuf->databuf = (uint8_t *)(nbuf + 1); - /* Scan to find existence of the device */ - if (nand_scan_ident(mtd, 2, NULL)) { - err = -ENXIO; - goto out_irq; - } + /* Restore the DMA flag */ + usedma = old_dma; cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ if (mtd->writesize == 2048) @@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, } else { printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", mtd->writesize); - goto out_irq; + goto out_free_dma; } cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; cafe->nand.ecc.size = mtd->writesize; @@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, err = nand_scan_tail(mtd); if (err) - goto out_irq; + goto out_free_dma; pci_set_drvdata(pdev, mtd); @@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev, goto out; + out_free_dma: + dma_free_coherent(&cafe->pdev->dev, + 2112 + sizeof(struct nand_buffers) + + mtd->writesize + mtd->oobsize, + cafe->dmabuf, cafe->dmaaddr); out_irq: /* Disable NAND IRQ in global IRQ mask register */ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); free_irq(pdev->irq, mtd); - out_free_dma: - dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); out_ior: pci_iounmap(pdev, cafe->mmio); out_free_mtd: @@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev) nand_release(mtd); free_rs(cafe->rs); pci_iounmap(pdev, cafe->mmio); - dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); + dma_free_coherent(&cafe->pdev->dev, + 2112 + sizeof(struct nand_buffers) + + mtd->writesize + mtd->oobsize, + cafe->dmabuf, cafe->dmaaddr); kfree(mtd); } diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index dd22cc4..21e1746 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3733,15 +3733,26 @@ int nand_scan_tail(struct mtd_info *mtd) int i; struct nand_chip *chip = mtd->priv; struct nand_ecc_ctrl *ecc = &chip->ecc; + struct nand_buffers *nbuf; /* New bad blocks should be marked in OOB, flash-based BBT, or both */ BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && !(chip->bbt_options & NAND_BBT_USE_FLASH)); - if (!(chip->options & NAND_OWN_BUFFERS)) - chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); - if (!chip->buffers) - return -ENOMEM; + if (!(chip->options & NAND_OWN_BUFFERS)) { + nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize + + mtd->oobsize * 3, GFP_KERNEL); + if (!nbuf) + return -ENOMEM; + nbuf->ecccalc = (uint8_t *)(nbuf + 1); + nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; + nbuf->databuf = nbuf->ecccode + mtd->oobsize; + + chip->buffers = nbuf; + } else { + if (!chip->buffers) + return -ENOMEM; + } /* Set the internal oob buffer location, just after the page data */ chip->oob_poi = chip->buffers->databuf + mtd->writesize; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index d06a56a..773bd93 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -481,17 +481,17 @@ struct nand_ecc_ctrl { /** * struct nand_buffers - buffer structure for read/write - * @ecccalc: buffer for calculated ECC - * @ecccode: buffer for ECC read from flash - * @databuf: buffer for data - dynamically sized + * @ecccalc: buffer pointer for calculated ECC, size is oobsize. + * @ecccode: buffer pointer for ECC read from flash, size is oobsize. + * @databuf: buffer pointer for data, size is (page size + oobsize). * * Do not change the order of buffers. databuf and oobrbuf must be in * consecutive order. */ struct nand_buffers { - uint8_t ecccalc[NAND_MAX_OOBSIZE]; - uint8_t ecccode[NAND_MAX_OOBSIZE]; - uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; + uint8_t *ecccalc; + uint8_t *ecccode; + uint8_t *databuf; }; /**