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

Commit cc548740 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-20170602' of git://git.infradead.org/linux-mtd

Pull MTD fixes from Brian Norris:
 "NAND updates from Boris:

  tango fixes:
   - Add missing MODULE_DEVICE_TABLE() in tango_nand.c
   - Update the number of corrected bitflips

  core fixes:
   - Fix a long standing memory leak in nand_scan_tail()
   - Fix several bugs introduced by the per-vendor init/detection
     infrastructure (introduced in 4.12)
   - Add a static specifier to nand_ooblayout_lp_hamming_ops definition"

* tag 'for-linus-20170602' of git://git.infradead.org/linux-mtd:
  mtd: nand: make nand_ooblayout_lp_hamming_ops static
  mtd: nand: tango: Update ecc_stats.corrected
  mtd: nand: tango: Export OF device ID table as module aliases
  mtd: nand: samsung: warn about un-parseable ECC info
  mtd: nand: free vendor-specific resources in init failure paths
  mtd: nand: drop unneeded module.h include
  mtd: nand: don't leak buffers when ->scan_bbt() fails
parents 104c08ba 05e97a9e
Loading
Loading
Loading
Loading
+35 −11
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
	return 0;
}

const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
	.ecc = nand_ooblayout_ecc_lp_hamming,
	.free = nand_ooblayout_free_lp_hamming,
};
@@ -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 */
@@ -4842,7 +4855,11 @@ int nand_scan_tail(struct mtd_info *mtd)
		return 0;

	/* Build bad block table */
	return chip->scan_bbt(mtd);
	ret = chip->scan_bbt(mtd);
	if (ret)
		goto err_free;
	return 0;

err_free:
	if (nbuf) {
		kfree(nbuf->databuf);
@@ -4850,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);
+0 −1
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@
 * published by the Free Software Foundation.
 *
 */
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/sizes.h>

+3 −0
Original line number Diff line number Diff line
@@ -84,6 +84,9 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
			case 7:
				chip->ecc_strength_ds = 60;
				break;
			default:
				WARN(1, "Could not decode ECC info");
				chip->ecc_step_ds = 0;
			}
		}
	} else {
+16 −7
Original line number Diff line number Diff line
@@ -55,10 +55,10 @@
 * byte 1 for other packets in the page (PKT_N, for N > 0)
 * ERR_COUNT_PKT_N is the max error count over all but the first packet.
 */
#define DECODE_OK_PKT_0(v)	((v) & BIT(7))
#define DECODE_OK_PKT_N(v)	((v) & BIT(15))
#define ERR_COUNT_PKT_0(v)	(((v) >> 0) & 0x3f)
#define ERR_COUNT_PKT_N(v)	(((v) >> 8) & 0x3f)
#define DECODE_FAIL_PKT_0(v)	(((v) & BIT(7)) == 0)
#define DECODE_FAIL_PKT_N(v)	(((v) & BIT(15)) == 0)

/* Offsets relative to pbus_base */
#define PBUS_CS_CTRL	0x83c
@@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
						  chip->ecc.strength);
		if (res < 0)
			mtd->ecc_stats.failed++;
		else
			mtd->ecc_stats.corrected += res;

		bitflips = max(res, bitflips);
		buf += pkt_size;
@@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
	return bitflips;
}

static int decode_error_report(struct tango_nfc *nfc)
static int decode_error_report(struct nand_chip *chip)
{
	u32 status, res;
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct tango_nfc *nfc = to_tango_nfc(chip->controller);

	status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
	if (status & PAGE_IS_EMPTY)
@@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc)

	res = readl_relaxed(nfc->mem_base + ERROR_REPORT);

	if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res))
		return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));

	if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res))
		return -EBADMSG;

	/* ERR_COUNT_PKT_N is max, not sum, but that's all we have */
	mtd->ecc_stats.corrected +=
		ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res);

	return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
}

static void tango_dma_callback(void *arg)
@@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
	if (err)
		return err;

	res = decode_error_report(nfc);
	res = decode_error_report(chip);
	if (res < 0) {
		chip->ecc.read_oob_raw(mtd, chip, page);
		res = check_erased_page(chip, buf);
@@ -663,6 +671,7 @@ static const struct of_device_id tango_nand_ids[] = {
	{ .compatible = "sigma,smp8758-nand" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tango_nand_ids);

static struct platform_driver tango_nand_driver = {
	.probe	= tango_nand_probe,