This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
My UBIFS image is mounting properly
the first time and after that I am facing a crash on subsequent boots. Also, I
observed that whenever a ‘sync’ operation is performed, the subsequent boot
fails. I get the following error notification :
http://www.linux-mtd.infradead.org/faq/ubi.html#L_ecc_error
As the page suggests, this issue is regarding the inability to differentiate between identifying 0xFF as an erased page or a data value. Has anyone come across such an issue? Is there a work around for this?
Thanks and Regards,
Parth
Hello Parth,
This basically is a bug in the NAND driver of both u-boot and kernel.
Please try the following patches :
U-boot :
drivers/mtd/nand/nand_base.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 618c5bf..5770177 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1877,11 +1877,25 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
-
+ int *tmp = (int *)buf ;
+ int count = 0;
+ int correctme = 0;
+
+ while((*tmp == 0xffffffff) && count < (eccsize * eccsteps) ) {
+ tmp++;
+ count += sizeof(int);
+ }
+
+ if (count >= (eccsize * eccsteps))
+ correctme = 1;
+
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
chip->write_buf(mtd, p, eccsize);
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+ if(correctme) {
+ memset(&ecc_calc[i], 0xff, eccbytes);
+ }
}
for (i = 0; i < chip->ecc.total; i++)
--
And for the kernel :
---
drivers/mtd/nand/nand_base.c | 32 +++++++++++++++++++++++++++++++-
1 files changed, 31 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ee265f1..b4da4d9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -50,6 +50,9 @@
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+static unsigned int ecc_subpage_flags;
+#endif
/* Define default oob placement schemes for large and small page devices */
static struct nand_ecclayout nand_oob_8 = {
@@ -1986,17 +1989,27 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
{
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+ int j;
+#endif
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
uint8_t *ecc_calc = chip->buffers->ecccalc;
const uint8_t *p = buf;
uint32_t *eccpos = chip->ecc.layout->eccpos;
-
+#ifndef CONFIG_TI8148_EVM_OPTIMIZED
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+#else
+ for (i = 0, j = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize, j++) {
+#endif
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
chip->write_buf(mtd, p, eccsize);
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+ if (!(ecc_subpage_flags & (1 << j)))
+ memset(&ecc_calc[i], 0xff, eccbytes);
+#endif
}
for (i = 0; i < chip->ecc.total; i++)
@@ -2223,6 +2236,12 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
int bytes = mtd->writesize;
int cached = writelen > bytes && page != blockmask;
uint8_t *wbuf = buf;
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+ int eccsize = chip->ecc.size;
+ int i, j;
+
+ ecc_subpage_flags = 0;
+#endif
/* Partial page write ? */
if (unlikely(column || writelen < (mtd->writesize - 1))) {
@@ -2232,7 +2251,18 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
memset(chip->buffers->databuf, 0xff, mtd->writesize);
memcpy(&chip->buffers->databuf[column], buf, bytes);
wbuf = chip->buffers->databuf;
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+ i = column / eccsize;
+ j = i + (writelen / eccsize);
+ for (; i < j; i++)
+ ecc_subpage_flags |= (1 << i);
+#endif
+
}
+#ifdef CONFIG_TI8148_EVM_OPTIMIZED
+ else
+ ecc_subpage_flags = ~0;
+#endif
if (unlikely(oob)) {
size_t len = min(oobwritelen, oobmaxlen);
--
Thanks & Regards,
Hrishikesh
Hi there Bob,
Regarding patch, I think this guide is pretty helpful: The 10 Minute Guide to Diff and Patch. I'd recommend backing things up before applying patches (or even better, ensure the code you're patching is under version control so you can undo anything that breaks.)
I also ran into issues when switching to UBIFS + BCH8 HWECC.
The solution for me was to switch from the kernel provided in the SDKs to the latest available in the Arago git repositories (for my processor, this was the linux-omap3.git repo), and then fixing a few issues in the parameters I used to generate the UBIFS and UBI images. You may find this thread helpful: DM8148 ECC issues: BCH8 + UBIFS
Unfortunately, I'm not using the IPNC SDK, so I cannot speak to the state of that SDK's kernel and how it differs from the contents of linux-omap3. However, take a look at the file history of the NAND-related files in linux-omap3 -- this might give you an idea of which fixes you can pull into your kernel.
Hope that sheds some light on a few things. Best of luck!
Jon