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>
This commit is contained in:
parent
e7beeeec85
commit
3deb9979c7
@ -4495,7 +4495,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||||||
{
|
{
|
||||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||||
struct nand_buffers *nbuf;
|
struct nand_buffers *nbuf = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* 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 */
|
||||||
@ -4509,13 +4509,28 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(chip->options & NAND_OWN_BUFFERS)) {
|
if (!(chip->options & NAND_OWN_BUFFERS)) {
|
||||||
nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
|
nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
|
||||||
+ mtd->oobsize * 3, GFP_KERNEL);
|
|
||||||
if (!nbuf)
|
if (!nbuf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
nbuf->ecccalc = (uint8_t *)(nbuf + 1);
|
|
||||||
nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
|
nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
|
||||||
nbuf->databuf = nbuf->ecccode + mtd->oobsize;
|
if (!nbuf->ecccalc) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbuf->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
|
||||||
|
if (!nbuf->ecccode) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbuf->databuf = kmalloc(mtd->writesize + mtd->oobsize,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!nbuf->databuf) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
chip->buffers = nbuf;
|
chip->buffers = nbuf;
|
||||||
} else {
|
} else {
|
||||||
@ -4755,8 +4770,12 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||||||
/* Build bad block table */
|
/* Build bad block table */
|
||||||
return chip->scan_bbt(mtd);
|
return chip->scan_bbt(mtd);
|
||||||
err_free:
|
err_free:
|
||||||
if (!(chip->options & NAND_OWN_BUFFERS))
|
if (nbuf) {
|
||||||
kfree(chip->buffers);
|
kfree(nbuf->databuf);
|
||||||
|
kfree(nbuf->ecccode);
|
||||||
|
kfree(nbuf->ecccalc);
|
||||||
|
kfree(nbuf);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nand_scan_tail);
|
EXPORT_SYMBOL(nand_scan_tail);
|
||||||
@ -4807,8 +4826,12 @@ void nand_cleanup(struct nand_chip *chip)
|
|||||||
|
|
||||||
/* Free bad block table memory */
|
/* Free bad block table memory */
|
||||||
kfree(chip->bbt);
|
kfree(chip->bbt);
|
||||||
if (!(chip->options & NAND_OWN_BUFFERS))
|
if (!(chip->options & NAND_OWN_BUFFERS) && chip->buffers) {
|
||||||
|
kfree(chip->buffers->databuf);
|
||||||
|
kfree(chip->buffers->ecccode);
|
||||||
|
kfree(chip->buffers->ecccalc);
|
||||||
kfree(chip->buffers);
|
kfree(chip->buffers);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free bad block descriptor memory */
|
/* Free bad block descriptor memory */
|
||||||
if (chip->badblock_pattern && chip->badblock_pattern->options
|
if (chip->badblock_pattern && chip->badblock_pattern->options
|
||||||
|
Loading…
Reference in New Issue
Block a user