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

Commit 3f91e94f authored by Mike Dunn's avatar Mike Dunn Committed by David Woodhouse
Browse files

mtd: nand: read_page() returns max_bitflips

The ecc.read_page() method for nand drivers is changed to return the maximum
number of bitflips that were corrected on any one region covering an ecc step,
This patch doesn't change what the nand code returns to mtd.

This v2 includes the change to the fsl_ifc_nand driver requested by Scott¹.

¹ http://lists.infradead.org/pipermail/linux-mtd/2012-April/040883.html



Signed-off-by: default avatarMike Dunn <mikedunn@newsguy.com>
Acked-by (freescale changes): Scott Wood <scottwood@freescale.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent d062d4ed
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -335,6 +335,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
	uint8_t *oob = chip->oob_poi;
	uint8_t *ecc_pos;
	int stat;
	unsigned int max_bitflips = 0;

	/*
	 * Errata: ALE is incorrectly wired up to the ECC controller
@@ -371,10 +372,12 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
	/* check if there's an error */
	stat = chip->ecc.correct(mtd, p, oob, NULL);

	if (stat < 0)
	if (stat < 0) {
		mtd->ecc_stats.failed++;
	else
	} else {
		mtd->ecc_stats.corrected += stat;
		max_bitflips = max_t(unsigned int, max_bitflips, stat);
	}

	/* get back to oob start (end of page) */
	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
@@ -382,7 +385,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
	/* read the oob */
	chip->read_buf(mtd, oob, mtd->oobsize);

	return 0;
	return max_bitflips;
}

/*
+3 −1
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
	uint8_t eccCalc[NAND_ECC_NUM_BYTES];
	int sectorOobSize = mtd->oobsize / eccsteps;
	int stat;
	unsigned int max_bitflips = 0;

	for (sectorIdx = 0; sectorIdx < eccsteps;
			sectorIdx++, datap += eccsize) {
@@ -177,9 +178,10 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
			}
#endif
			mtd->ecc_stats.corrected += stat;
			max_bitflips = max_t(unsigned int, max_bitflips, stat);
		}
	}
	return 0;
	return max_bitflips;
}

/****************************************************************************
+3 −1
Original line number Diff line number Diff line
@@ -383,6 +383,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
			       uint8_t *buf, int page)
{
	struct cafe_priv *cafe = mtd->priv;
	unsigned int max_bitflips = 0;

	cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
		     cafe_readl(cafe, NAND_ECC_RESULT),
@@ -449,10 +450,11 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
		} else {
			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
			mtd->ecc_stats.corrected += n;
			max_bitflips = max_t(unsigned int, max_bitflips, n);
		}
	}

	return 0;
	return max_bitflips;
}

static struct nand_ecclayout cafe_oobinfo_2048 = {
+7 −3
Original line number Diff line number Diff line
@@ -924,9 +924,10 @@ bool is_erased(uint8_t *buf, int len)
#define ECC_LAST_ERR(x)		((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)

static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
					uint32_t irq_status)
		       uint32_t irq_status, unsigned int *max_bitflips)
{
	bool check_erased_page = false;
	unsigned int bitflips = 0;

	if (irq_status & INTR_STATUS__ECC_ERR) {
		/* read the ECC errors. we'll ignore them for now */
@@ -965,6 +966,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
					/* correct the ECC error */
					buf[offset] ^= err_correction_value;
					denali->mtd.ecc_stats.corrected++;
					bitflips++;
				}
			} else {
				/* if the error is not correctable, need to
@@ -984,6 +986,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
		clear_interrupts(denali);
		denali_set_intr_modes(denali, true);
	}
	*max_bitflips = bitflips;
	return check_erased_page;
}

@@ -1121,6 +1124,7 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
			    uint8_t *buf, int page)
{
	unsigned int max_bitflips;
	struct denali_nand_info *denali = mtd_to_denali(mtd);

	dma_addr_t addr = denali->buf.dma_buf;
@@ -1153,7 +1157,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,

	memcpy(buf, denali->buf.buf, mtd->writesize);

	check_erased_page = handle_ecc(denali, buf, irq_status);
	check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips);
	denali_enable_dma(denali, false);

	if (check_erased_page) {
@@ -1167,7 +1171,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
				denali->mtd.ecc_stats.failed++;
		}
	}
	return 0;
	return max_bitflips;
}

static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+3 −2
Original line number Diff line number Diff line
@@ -720,6 +720,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
	struct docg4_priv *doc = nand->priv;
	void __iomem *docptr = doc->virtadr;
	uint16_t status, edc_err, *buf16;
	int bits_corrected = 0;

	dev_dbg(doc->dev, "%s: page %08x\n", __func__, page);

@@ -772,7 +773,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,

		/* If bitflips are reported, attempt to correct with ecc */
		if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
			int bits_corrected = correct_data(mtd, buf, page);
			bits_corrected = correct_data(mtd, buf, page);
			if (bits_corrected == -EBADMSG)
				mtd->ecc_stats.failed++;
			else
@@ -781,7 +782,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
	}

	writew(0, docptr + DOC_DATAEND);
	return 0;
	return bits_corrected;
}


Loading