aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang Shijie <b32955@freescale.com>2014-01-13 01:27:12 -0500
committerBrian Norris <computersforpeace@gmail.com>2014-03-11 01:42:22 -0400
commitf02ea4e6a47d50a38f5baadbe87f5087dd337db0 (patch)
tree512c46fb2f1761c456cb5eedf02e06d57f50fb63
parent3ea5b037e750274659648b58fb97426566a90373 (diff)
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: Huang Shijie <b32955@freescale.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r--drivers/mtd/nand/cafe_nand.c68
-rw-r--r--drivers/mtd/nand/nand_base.c19
-rw-r--r--include/linux/mtd/nand.h12
3 files changed, 67 insertions, 32 deletions
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index f2f64addb5e8..4e66726da9aa 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,
627 struct cafe_priv *cafe; 627 struct cafe_priv *cafe;
628 uint32_t ctrl; 628 uint32_t ctrl;
629 int err = 0; 629 int err = 0;
630 int old_dma;
631 struct nand_buffers *nbuf;
630 632
631 /* Very old versions shared the same PCI ident for all three 633 /* Very old versions shared the same PCI ident for all three
632 functions on the chip. Verify the class too... */ 634 functions on the chip. Verify the class too... */
@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
655 err = -ENOMEM; 657 err = -ENOMEM;
656 goto out_free_mtd; 658 goto out_free_mtd;
657 } 659 }
658 cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
659 &cafe->dmaaddr, GFP_KERNEL);
660 if (!cafe->dmabuf) {
661 err = -ENOMEM;
662 goto out_ior;
663 }
664 cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
665 660
666 cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); 661 cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
667 if (!cafe->rs) { 662 if (!cafe->rs) {
@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
721 "CAFE NAND", mtd); 716 "CAFE NAND", mtd);
722 if (err) { 717 if (err) {
723 dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); 718 dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
724 goto out_free_dma; 719 goto out_ior;
725 } 720 }
726 721
727 /* Disable master reset, enable NAND clock */ 722 /* Disable master reset, enable NAND clock */
@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev,
735 cafe_writel(cafe, 0x7006, GLOBAL_CTRL); 730 cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
736 cafe_writel(cafe, 0x700a, GLOBAL_CTRL); 731 cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
737 732
733 /* Enable NAND IRQ in global IRQ mask register */
734 cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
735 cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
736 cafe_readl(cafe, GLOBAL_CTRL),
737 cafe_readl(cafe, GLOBAL_IRQ_MASK));
738
739 /* Do not use the DMA for the nand_scan_ident() */
740 old_dma = usedma;
741 usedma = 0;
742
743 /* Scan to find existence of the device */
744 if (nand_scan_ident(mtd, 2, NULL)) {
745 err = -ENXIO;
746 goto out_irq;
747 }
748
749 cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev,
750 2112 + sizeof(struct nand_buffers) +
751 mtd->writesize + mtd->oobsize,
752 &cafe->dmaaddr, GFP_KERNEL);
753 if (!cafe->dmabuf) {
754 err = -ENOMEM;
755 goto out_irq;
756 }
757 cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112;
758
738 /* Set up DMA address */ 759 /* Set up DMA address */
739 cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); 760 cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
740 if (sizeof(cafe->dmaaddr) > 4) 761 if (sizeof(cafe->dmaaddr) > 4)
@@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev,
746 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", 767 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
747 cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); 768 cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
748 769
749 /* Enable NAND IRQ in global IRQ mask register */ 770 /* this driver does not need the @ecccalc and @ecccode */
750 cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); 771 nbuf->ecccalc = NULL;
751 cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", 772 nbuf->ecccode = NULL;
752 cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); 773 nbuf->databuf = (uint8_t *)(nbuf + 1);
753 774
754 /* Scan to find existence of the device */ 775 /* Restore the DMA flag */
755 if (nand_scan_ident(mtd, 2, NULL)) { 776 usedma = old_dma;
756 err = -ENXIO;
757 goto out_irq;
758 }
759 777
760 cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ 778 cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
761 if (mtd->writesize == 2048) 779 if (mtd->writesize == 2048)
@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
773 } else { 791 } else {
774 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", 792 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
775 mtd->writesize); 793 mtd->writesize);
776 goto out_irq; 794 goto out_free_dma;
777 } 795 }
778 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; 796 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
779 cafe->nand.ecc.size = mtd->writesize; 797 cafe->nand.ecc.size = mtd->writesize;
@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
790 808
791 err = nand_scan_tail(mtd); 809 err = nand_scan_tail(mtd);
792 if (err) 810 if (err)
793 goto out_irq; 811 goto out_free_dma;
794 812
795 pci_set_drvdata(pdev, mtd); 813 pci_set_drvdata(pdev, mtd);
796 814
@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev,
799 817
800 goto out; 818 goto out;
801 819
820 out_free_dma:
821 dma_free_coherent(&cafe->pdev->dev,
822 2112 + sizeof(struct nand_buffers) +
823 mtd->writesize + mtd->oobsize,
824 cafe->dmabuf, cafe->dmaaddr);
802 out_irq: 825 out_irq:
803 /* Disable NAND IRQ in global IRQ mask register */ 826 /* Disable NAND IRQ in global IRQ mask register */
804 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); 827 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
805 free_irq(pdev->irq, mtd); 828 free_irq(pdev->irq, mtd);
806 out_free_dma:
807 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
808 out_ior: 829 out_ior:
809 pci_iounmap(pdev, cafe->mmio); 830 pci_iounmap(pdev, cafe->mmio);
810 out_free_mtd: 831 out_free_mtd:
@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev)
824 nand_release(mtd); 845 nand_release(mtd);
825 free_rs(cafe->rs); 846 free_rs(cafe->rs);
826 pci_iounmap(pdev, cafe->mmio); 847 pci_iounmap(pdev, cafe->mmio);
827 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); 848 dma_free_coherent(&cafe->pdev->dev,
849 2112 + sizeof(struct nand_buffers) +
850 mtd->writesize + mtd->oobsize,
851 cafe->dmabuf, cafe->dmaaddr);
828 kfree(mtd); 852 kfree(mtd);
829} 853}
830 854
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9715a7ba164a..deeaa1cc4a85 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3696,15 +3696,26 @@ int nand_scan_tail(struct mtd_info *mtd)
3696 int i; 3696 int i;
3697 struct nand_chip *chip = mtd->priv; 3697 struct nand_chip *chip = mtd->priv;
3698 struct nand_ecc_ctrl *ecc = &chip->ecc; 3698 struct nand_ecc_ctrl *ecc = &chip->ecc;
3699 struct nand_buffers *nbuf;
3699 3700
3700 /* New bad blocks should be marked in OOB, flash-based BBT, or both */ 3701 /* New bad blocks should be marked in OOB, flash-based BBT, or both */
3701 BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && 3702 BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
3702 !(chip->bbt_options & NAND_BBT_USE_FLASH)); 3703 !(chip->bbt_options & NAND_BBT_USE_FLASH));
3703 3704
3704 if (!(chip->options & NAND_OWN_BUFFERS)) 3705 if (!(chip->options & NAND_OWN_BUFFERS)) {
3705 chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); 3706 nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
3706 if (!chip->buffers) 3707 + mtd->oobsize * 3, GFP_KERNEL);
3707 return -ENOMEM; 3708 if (!nbuf)
3709 return -ENOMEM;
3710 nbuf->ecccalc = (uint8_t *)(nbuf + 1);
3711 nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
3712 nbuf->databuf = nbuf->ecccode + mtd->oobsize;
3713
3714 chip->buffers = nbuf;
3715 } else {
3716 if (!chip->buffers)
3717 return -ENOMEM;
3718 }
3708 3719
3709 /* Set the internal oob buffer location, just after the page data */ 3720 /* Set the internal oob buffer location, just after the page data */
3710 chip->oob_poi = chip->buffers->databuf + mtd->writesize; 3721 chip->oob_poi = chip->buffers->databuf + mtd->writesize;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 32f8612469d8..520ebca11f5d 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -435,17 +435,17 @@ struct nand_ecc_ctrl {
435 435
436/** 436/**
437 * struct nand_buffers - buffer structure for read/write 437 * struct nand_buffers - buffer structure for read/write
438 * @ecccalc: buffer for calculated ECC 438 * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
439 * @ecccode: buffer for ECC read from flash 439 * @ecccode: buffer pointer for ECC read from flash, size is oobsize.
440 * @databuf: buffer for data - dynamically sized 440 * @databuf: buffer pointer for data, size is (page size + oobsize).
441 * 441 *
442 * Do not change the order of buffers. databuf and oobrbuf must be in 442 * Do not change the order of buffers. databuf and oobrbuf must be in
443 * consecutive order. 443 * consecutive order.
444 */ 444 */
445struct nand_buffers { 445struct nand_buffers {
446 uint8_t ecccalc[NAND_MAX_OOBSIZE]; 446 uint8_t *ecccalc;
447 uint8_t ecccode[NAND_MAX_OOBSIZE]; 447 uint8_t *ecccode;
448 uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; 448 uint8_t *databuf;
449}; 449};
450 450
451/** 451/**