mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michael Grzeschik <m.grzeschik@pengutronix.de>
To: linux-mtd@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, dwmw2@infradead.org, kernel@pengutronix.de
Subject: [PATCH 2/2] mxc_nand: use our own read_page function
Date: Thu, 26 Jun 2014 22:42:48 +0200	[thread overview]
Message-ID: <1403815368-29469-2-git-send-email-m.grzeschik@pengutronix.de> (raw)
In-Reply-To: <1403815368-29469-1-git-send-email-m.grzeschik@pengutronix.de>

The current approach of the read_page function is to iterate over all
subpages and call the correct_data function. The correct_data function
currently does the same. It iterates over all subpages and checks for
correctable and uncorrectable data. This redundant call for each
subpage leads to miscalculations.

This patch changes the driver to use its own read_page function in which
we call the correct_data function only once per page. With that we do
the failure and correct statistics counting inside this function.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/mtd/nand/mxc_nand.c | 73 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 7fd495e..09e3682 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -141,6 +141,8 @@ struct mxc_nand_host;
 
 struct mxc_nand_devtype_data {
 	void (*preset)(struct mtd_info *);
+	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint8_t *buf, int oob_required, int page);
 	void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
 	void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
 	void (*send_page)(struct mtd_info *, unsigned int);
@@ -649,6 +651,59 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
 	return 0;
 }
 
+/**
+ * mxc_nand_read_page_hwecc_v2_v3 - [REPLACEABLE] hardware ECC based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
+ * @page: page number to read
+ *
+ * Not for syndrome calculating ECC controllers which need a special oob layout.
+ */
+static int
+mxc_nand_read_page_hwecc_v2_v3(struct mtd_info *mtd,
+			       struct nand_chip *chip,
+			       uint8_t *buf, int oob_required, int page)
+{
+	int i, eccsize = chip->ecc.size;
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
+	uint8_t *ecc_code = chip->buffers->ecccode;
+	uint32_t *eccpos = chip->ecc.layout->eccpos;
+	unsigned int max_bitflips = 0;
+	u32 ecc_stat, err;
+	int stat;
+
+	ecc_stat = host->devtype_data->get_ecc_status(host);
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		err = ecc_stat & 0xf;
+		chip->ecc.hwctl(mtd, NAND_ECC_READ);
+		chip->read_buf(mtd, p, eccsize);
+		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+		ecc_stat >>= 4;
+
+	}
+	ecc_stat = host->devtype_data->get_ecc_status(host);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	for (i = 0; i < chip->ecc.total; i++)
+		ecc_code[i] = chip->oob_poi[eccpos[i]];
+
+	eccsteps = chip->ecc.steps;
+	p = buf;
+
+	stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+	max_bitflips = max_t(unsigned int, max_bitflips, stat);
+
+	return max_bitflips;
+}
+
+
 static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
@@ -656,7 +711,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
 	struct mxc_nand_host *host = nand_chip->priv;
 	u32 ecc_stat, err;
 	int no_subpages = 1;
-	int ret = 0;
+	int ret = 0, broken = 0;
 	u8 ecc_bit_mask, err_limit = 0x1;
 
 	ecc_bit_mask = 0xf;
@@ -673,15 +728,21 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
 	do {
 		err = ecc_stat & ecc_bit_mask;
 		if (err > err_limit) {
-			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
-			return -1;
+			broken++;
 		} else {
 			ret += err;
 		}
 		ecc_stat >>= 4;
 	} while (--no_subpages);
 
-	pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
+	mtd->ecc_stats.corrected += ret;
+	if (ret)
+		printk("%d Symbol Correctable RS-ECC Error\n", ret);
+
+	mtd->ecc_stats.failed += broken;
+	if (broken)
+		printk(KERN_WARNING "%d Symbol UnCorrectable RS-ECC Error\n",
+			 broken);
 
 	return ret;
 }
@@ -1244,6 +1305,7 @@ static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
 /* v21: i.MX25, i.MX35 */
 static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
 	.preset = preset_v2,
+	.read_page = mxc_nand_read_page_hwecc_v2_v3,
 	.send_cmd = send_cmd_v1_v2,
 	.send_addr = send_addr_v1_v2,
 	.send_page = send_page_v2,
@@ -1270,6 +1332,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
 /* v3.2a: i.MX51 */
 static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
 	.preset = preset_v3,
+	.read_page = mxc_nand_read_page_hwecc_v2_v3,
 	.send_cmd = send_cmd_v3,
 	.send_addr = send_addr_v3,
 	.send_page = send_page_v3,
@@ -1297,6 +1360,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
 /* v3.2b: i.MX53 */
 static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
 	.preset = preset_v3,
+	.read_page = mxc_nand_read_page_hwecc_v2_v3,
 	.send_cmd = send_cmd_v3,
 	.send_addr = send_addr_v3,
 	.send_page = send_page_v3,
@@ -1517,6 +1581,7 @@ static int mxcnd_probe(struct platform_device *pdev)
 	this->ecc.layout = host->devtype_data->ecclayout_512;
 
 	if (host->pdata.hw_ecc) {
+		this->ecc.read_page = host->devtype_data->read_page;
 		this->ecc.calculate = mxc_nand_calculate_ecc;
 		this->ecc.hwctl = mxc_nand_enable_hwecc;
 		this->ecc.correct = host->devtype_data->correct_data;
-- 
2.0.0


  reply	other threads:[~2014-06-26 20:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-26 20:42 [PATCH 1/2] mxc_nand: fix err_limit and err_mask Michael Grzeschik
2014-06-26 20:42 ` Michael Grzeschik [this message]
2014-06-27  9:19   ` [PATCH 2/2] mxc_nand: use our own read_page function Michael Grzeschik
2014-06-27 10:38   ` [PATH v2] " Michael Grzeschik
2014-07-05 14:45     ` Michael Grzeschik
2014-07-14 13:28       ` Michael Grzeschik
2014-07-14 19:19     ` Brian Norris
2014-07-22 10:09       ` Michael Grzeschik
2014-07-22 19:23         ` Brian Norris
2014-07-22  3:21 ` [PATCH 1/2] mxc_nand: fix err_limit and err_mask Brian Norris

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403815368-29469-2-git-send-email-m.grzeschik@pengutronix.de \
    --to=m.grzeschik@pengutronix.de \
    --cc=dwmw2@infradead.org \
    --cc=kernel@pengutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®