diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2017-03-30 04:15:04 -0400 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2017-04-25 08:18:37 -0400 |
commit | 3deb9979c7319bc7846d1aac528a9db85162960a (patch) | |
tree | 461a23ff5a0761e5940c3b6db229bd85f5dc1082 /drivers/mtd/nand | |
parent | e7beeeec854c40c28caa53bd84fdf26e9e459f06 (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.c | 41 |
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); |
4757 | err_free: | 4772 | err_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 | } |
4762 | EXPORT_SYMBOL(nand_scan_tail); | 4781 | EXPORT_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 |