Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
	/* Initialize the ->data_interface field. */
	ret = nand_init_data_interface(chip);
	if (ret)
		return ret;
		goto err_nand_init;

	/*
	 * 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,
	 */
	ret = nand_setup_data_interface(chip);
	if (ret)
		return ret;
		goto err_nand_init;

	nand_maf_id = chip->id.data[0];
	nand_dev_id = chip->id.data[1];
@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
	mtd->size = i * chip->chipsize;

	return 0;

err_nand_init:
	/* Free manufacturer priv data. */
	nand_manufacturer_cleanup(chip);

	return ret;
}
EXPORT_SYMBOL(nand_scan_ident);

@@ -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 */
	if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
		   !(chip->bbt_options & NAND_BBT_USE_FLASH)))
		return -EINVAL;
		   !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
		ret = -EINVAL;
		goto err_ident;
	}

	if (invalid_ecc_page_accessors(chip)) {
		pr_err("Invalid ECC page accessors setup\n");
		return -EINVAL;
		ret = -EINVAL;
		goto err_ident;
	}

	if (!(chip->options & NAND_OWN_BUFFERS)) {
		nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
		if (!nbuf)
			return -ENOMEM;
		if (!nbuf) {
			ret = -ENOMEM;
			goto err_ident;
		}

		nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
		if (!nbuf->ecccalc) {
@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd)

		chip->buffers = nbuf;
	} else {
		if (!chip->buffers)
			return -ENOMEM;
		if (!chip->buffers) {
			ret = -ENOMEM;
			goto err_ident;
		}
	}

	/* Set the internal oob buffer location, just after the page data */
@@ -4854,6 +4867,13 @@ int nand_scan_tail(struct mtd_info *mtd)
		kfree(nbuf->ecccalc);
		kfree(nbuf);
	}

err_ident:
	/* Clean up nand_scan_ident(). */

	/* Free manufacturer priv data. */
	nand_manufacturer_cleanup(chip);

	return ret;
}
EXPORT_SYMBOL(nand_scan_tail);