summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2017-03-30 04:15:04 -0400
committerBoris Brezillon <boris.brezillon@free-electrons.com>2017-04-25 08:18:37 -0400
commit3deb9979c7319bc7846d1aac528a9db85162960a (patch)
tree461a23ff5a0761e5940c3b6db229bd85f5dc1082 /drivers/mtd/nand
parente7beeeec854c40c28caa53bd84fdf26e9e459f06 (diff)
mtd: nand: allocate aligned buffers if NAND_OWN_BUFFERS is unset
Some NAND controllers are using DMA engine requiring a specific buffer alignment. The core provides no guarantee on the nand_buffers pointers, which forces some drivers to allocate their own buffers and pass the NAND_OWN_BUFFERS flag. Rework the nand_buffers allocation logic to allocate each buffer independently. This should make most NAND controllers/DMA engine happy, and allow us to get rid of these custom buf allocation in NAND controller drivers. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/nand_base.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index de6c8045c85b..c796d0e4039a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -4495,7 +4495,7 @@ int nand_scan_tail(struct mtd_info *mtd)
4495{ 4495{
4496 struct nand_chip *chip = mtd_to_nand(mtd); 4496 struct nand_chip *chip = mtd_to_nand(mtd);
4497 struct nand_ecc_ctrl *ecc = &chip->ecc; 4497 struct nand_ecc_ctrl *ecc = &chip->ecc;
4498 struct nand_buffers *nbuf; 4498 struct nand_buffers *nbuf = NULL;
4499 int ret; 4499 int ret;
4500 4500
4501 /* New bad blocks should be marked in OOB, flash-based BBT, or both */ 4501 /* New bad blocks should be marked in OOB, flash-based BBT, or both */
@@ -4509,13 +4509,28 @@ int nand_scan_tail(struct mtd_info *mtd)
4509 } 4509 }
4510 4510
4511 if (!(chip->options & NAND_OWN_BUFFERS)) { 4511 if (!(chip->options & NAND_OWN_BUFFERS)) {
4512 nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize 4512 nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
4513 + mtd->oobsize * 3, GFP_KERNEL);
4514 if (!nbuf) 4513 if (!nbuf)
4515 return -ENOMEM; 4514 return -ENOMEM;
4516 nbuf->ecccalc = (uint8_t *)(nbuf + 1); 4515
4517 nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; 4516 nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
4518 nbuf->databuf = nbuf->ecccode + mtd->oobsize; 4517 if (!nbuf->ecccalc) {
4518 ret = -ENOMEM;
4519 goto err_free;
4520 }
4521
4522 nbuf->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
4523 if (!nbuf->ecccode) {
4524 ret = -ENOMEM;
4525 goto err_free;
4526 }
4527
4528 nbuf->databuf = kmalloc(mtd->writesize + mtd->oobsize,
4529 GFP_KERNEL);
4530 if (!nbuf->databuf) {
4531 ret = -ENOMEM;
4532 goto err_free;
4533 }
4519 4534
4520 chip->buffers = nbuf; 4535 chip->buffers = nbuf;
4521 } else { 4536 } else {
@@ -4755,8 +4770,12 @@ int nand_scan_tail(struct mtd_info *mtd)
4755 /* Build bad block table */ 4770 /* Build bad block table */
4756 return chip->scan_bbt(mtd); 4771 return chip->scan_bbt(mtd);
4757err_free: 4772err_free:
4758 if (!(chip->options & NAND_OWN_BUFFERS)) 4773 if (nbuf) {
4759 kfree(chip->buffers); 4774 kfree(nbuf->databuf);
4775 kfree(nbuf->ecccode);
4776 kfree(nbuf->ecccalc);
4777 kfree(nbuf);
4778 }
4760 return ret; 4779 return ret;
4761} 4780}
4762EXPORT_SYMBOL(nand_scan_tail); 4781EXPORT_SYMBOL(nand_scan_tail);
@@ -4807,8 +4826,12 @@ void nand_cleanup(struct nand_chip *chip)
4807 4826
4808 /* Free bad block table memory */ 4827 /* Free bad block table memory */
4809 kfree(chip->bbt); 4828 kfree(chip->bbt);
4810 if (!(chip->options & NAND_OWN_BUFFERS)) 4829 if (!(chip->options & NAND_OWN_BUFFERS) && chip->buffers) {
4830 kfree(chip->buffers->databuf);
4831 kfree(chip->buffers->ecccode);
4832 kfree(chip->buffers->ecccalc);
4811 kfree(chip->buffers); 4833 kfree(chip->buffers);
4834 }
4812 4835
4813 /* Free bad block descriptor memory */ 4836 /* Free bad block descriptor memory */
4814 if (chip->badblock_pattern && chip->badblock_pattern->options 4837 if (chip->badblock_pattern && chip->badblock_pattern->options