Commit 78771049 authored by Brian Norris's avatar Brian Norris Committed by Boris Brezillon

mtd: nand: free vendor-specific resources in init failure paths

If we fail any time after calling nand_detect(), then we don't call the
vendor-specific ->cleanup() callback, and we'll leak any resources the
vendor-specific code might have allocated.

Mark the "fix" against the first commit that started allocating anything
in ->init().

Fixes: 626994e0 ("mtd: nand: hynix: Add read-retry support for 1x nm MLC NANDs")
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent 0545c172
...@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, ...@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
/* Initialize the ->data_interface field. */ /* Initialize the ->data_interface field. */
ret = nand_init_data_interface(chip); ret = nand_init_data_interface(chip);
if (ret) if (ret)
return ret; goto err_nand_init;
/* /*
* Setup the data interface correctly on the chip and controller side. * Setup the data interface correctly on the chip and controller side.
...@@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, ...@@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
*/ */
ret = nand_setup_data_interface(chip); ret = nand_setup_data_interface(chip);
if (ret) if (ret)
return ret; goto err_nand_init;
nand_maf_id = chip->id.data[0]; nand_maf_id = chip->id.data[0];
nand_dev_id = chip->id.data[1]; nand_dev_id = chip->id.data[1];
...@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, ...@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
mtd->size = i * chip->chipsize; mtd->size = i * chip->chipsize;
return 0; return 0;
err_nand_init:
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
return ret;
} }
EXPORT_SYMBOL(nand_scan_ident); EXPORT_SYMBOL(nand_scan_ident);
...@@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd)
/* 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 */
if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
!(chip->bbt_options & NAND_BBT_USE_FLASH))) !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
return -EINVAL; ret = -EINVAL;
goto err_ident;
}
if (invalid_ecc_page_accessors(chip)) { if (invalid_ecc_page_accessors(chip)) {
pr_err("Invalid ECC page accessors setup\n"); pr_err("Invalid ECC page accessors setup\n");
return -EINVAL; ret = -EINVAL;
goto err_ident;
} }
if (!(chip->options & NAND_OWN_BUFFERS)) { if (!(chip->options & NAND_OWN_BUFFERS)) {
nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL); nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
if (!nbuf) if (!nbuf) {
return -ENOMEM; ret = -ENOMEM;
goto err_ident;
}
nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL); nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
if (!nbuf->ecccalc) { if (!nbuf->ecccalc) {
...@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->buffers = nbuf; chip->buffers = nbuf;
} else { } else {
if (!chip->buffers) if (!chip->buffers) {
return -ENOMEM; ret = -ENOMEM;
goto err_ident;
}
} }
/* Set the internal oob buffer location, just after the page data */ /* Set the internal oob buffer location, just after the page data */
...@@ -4854,6 +4867,13 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4854,6 +4867,13 @@ int nand_scan_tail(struct mtd_info *mtd)
kfree(nbuf->ecccalc); kfree(nbuf->ecccalc);
kfree(nbuf); kfree(nbuf);
} }
err_ident:
/* Clean up nand_scan_ident(). */
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
return ret; return ret;
} }
EXPORT_SYMBOL(nand_scan_tail); EXPORT_SYMBOL(nand_scan_tail);
......
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