Commit f02ea4e6 authored by Huang Shijie's avatar Huang Shijie Committed by Brian Norris

mtd: nand: kill the the NAND_MAX_PAGESIZE/NAND_MAX_OOBSIZE for nand_buffers{}

The patch converts the arrays to buffer pointers for nand_buffers{}.

The cafe_nand.c is the only NAND_OWN_BUFFERS user which allocates
nand_buffers{} itself.

This patch disables the DMA for nand_scan_ident, and restores the DMA
status after we finish the nand_scan_ident. This way, we can get page
size and OOB size and use them to allocate cafe->dmabuf.

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: default avatarHuang Shijie <b32955@freescale.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 3ea5b037
...@@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
struct cafe_priv *cafe; struct cafe_priv *cafe;
uint32_t ctrl; uint32_t ctrl;
int err = 0; int err = 0;
int old_dma;
struct nand_buffers *nbuf;
/* Very old versions shared the same PCI ident for all three /* Very old versions shared the same PCI ident for all three
functions on the chip. Verify the class too... */ functions on the chip. Verify the class too... */
...@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
err = -ENOMEM; err = -ENOMEM;
goto out_free_mtd; 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); cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
if (!cafe->rs) { if (!cafe->rs) {
...@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
"CAFE NAND", mtd); "CAFE NAND", mtd);
if (err) { if (err) {
dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); 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 */ /* Disable master reset, enable NAND clock */
...@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev,
cafe_writel(cafe, 0x7006, GLOBAL_CTRL); cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
cafe_writel(cafe, 0x700a, 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 */ /* Set up DMA address */
cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
if (sizeof(cafe->dmaaddr) > 4) if (sizeof(cafe->dmaaddr) > 4)
...@@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -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_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
/* Enable NAND IRQ in global IRQ mask register */ /* this driver does not need the @ecccalc and @ecccode */
cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); nbuf->ecccalc = NULL;
cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", nbuf->ecccode = NULL;
cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); nbuf->databuf = (uint8_t *)(nbuf + 1);
/* Scan to find existence of the device */ /* Restore the DMA flag */
if (nand_scan_ident(mtd, 2, NULL)) { usedma = old_dma;
err = -ENXIO;
goto out_irq;
}
cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
if (mtd->writesize == 2048) if (mtd->writesize == 2048)
...@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
} else { } else {
printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
mtd->writesize); mtd->writesize);
goto out_irq; goto out_free_dma;
} }
cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
cafe->nand.ecc.size = mtd->writesize; cafe->nand.ecc.size = mtd->writesize;
...@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
err = nand_scan_tail(mtd); err = nand_scan_tail(mtd);
if (err) if (err)
goto out_irq; goto out_free_dma;
pci_set_drvdata(pdev, mtd); pci_set_drvdata(pdev, mtd);
...@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev, ...@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev,
goto out; 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: out_irq:
/* Disable NAND IRQ in global IRQ mask register */ /* Disable NAND IRQ in global IRQ mask register */
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
free_irq(pdev->irq, mtd); free_irq(pdev->irq, mtd);
out_free_dma:
dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
out_ior: out_ior:
pci_iounmap(pdev, cafe->mmio); pci_iounmap(pdev, cafe->mmio);
out_free_mtd: out_free_mtd:
...@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev) ...@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev)
nand_release(mtd); nand_release(mtd);
free_rs(cafe->rs); free_rs(cafe->rs);
pci_iounmap(pdev, cafe->mmio); 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); kfree(mtd);
} }
......
...@@ -3696,15 +3696,26 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -3696,15 +3696,26 @@ int nand_scan_tail(struct mtd_info *mtd)
int i; int i;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_ecc_ctrl *ecc = &chip->ecc;
struct nand_buffers *nbuf;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */ /* New bad blocks should be marked in OOB, flash-based BBT, or both */
BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
!(chip->bbt_options & NAND_BBT_USE_FLASH)); !(chip->bbt_options & NAND_BBT_USE_FLASH));
if (!(chip->options & NAND_OWN_BUFFERS)) if (!(chip->options & NAND_OWN_BUFFERS)) {
chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
if (!chip->buffers) + mtd->oobsize * 3, GFP_KERNEL);
return -ENOMEM; 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 */ /* Set the internal oob buffer location, just after the page data */
chip->oob_poi = chip->buffers->databuf + mtd->writesize; chip->oob_poi = chip->buffers->databuf + mtd->writesize;
......
...@@ -435,17 +435,17 @@ struct nand_ecc_ctrl { ...@@ -435,17 +435,17 @@ struct nand_ecc_ctrl {
/** /**
* struct nand_buffers - buffer structure for read/write * struct nand_buffers - buffer structure for read/write
* @ecccalc: buffer for calculated ECC * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
* @ecccode: buffer for ECC read from flash * @ecccode: buffer pointer for ECC read from flash, size is oobsize.
* @databuf: buffer for data - dynamically sized * @databuf: buffer pointer for data, size is (page size + oobsize).
* *
* Do not change the order of buffers. databuf and oobrbuf must be in * Do not change the order of buffers. databuf and oobrbuf must be in
* consecutive order. * consecutive order.
*/ */
struct nand_buffers { struct nand_buffers {
uint8_t ecccalc[NAND_MAX_OOBSIZE]; uint8_t *ecccalc;
uint8_t ecccode[NAND_MAX_OOBSIZE]; uint8_t *ecccode;
uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; uint8_t *databuf;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment