mtd/drivers/mtd/nand diskonchip.c,1.13,1.14
dbrown at infradead.org
dbrown at infradead.org
Fri Jun 18 18:56:51 EDT 2004
Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv16605
Modified Files:
diskonchip.c
Log Message:
Fix problems caused because ECC bytes of an erased page != computed ECC over all 0xff data. Add an option to supress uncorrectable ECC errors for debugging.
Index: diskonchip.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/diskonchip.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- diskonchip.c 18 Jun 2004 00:51:39 -0000 1.13
+++ diskonchip.c 18 Jun 2004 22:56:48 -0000 1.14
@@ -33,6 +33,13 @@
int curchip;
};
+/* This is the syndrome computed by the HW ecc generator upon reading an empty
+ page, one with all 0xff for data and stored ecc code. */
+static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
+/* This is the ecc value computed by the HW ecc generator upon writing an empty
+ page, one with all 0xff for data. */
+static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
+
static char inftl_bbt_pattern[] = "MSYS_BBT";
static struct nand_bbt_descr inftl_bbt_descr = {
@@ -55,6 +62,9 @@
static int try_dword=1;
MODULE_PARM(try_dword, "i");
+static int no_ecc_failures=0;
+MODULE_PARM(no_ecc_failures, "i");
+
static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
{
volatile char dummy;
@@ -470,6 +480,7 @@
struct doc_priv *doc = (void *)this->priv;
unsigned long docptr = doc->virtadr;
int i;
+ int emptymatch = 1;
/* flush the pipeline */
if (DoC_is_2000(doc)) {
@@ -484,9 +495,24 @@
WriteDOC(0, docptr, NOP);
}
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++) {
ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
+ if (ecc_code[i] != empty_write_ecc[i])
+ emptymatch = 0;
+ }
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+ /* If emptymatch=1, we might have an all-0xff data buffer. Check. */
+ if (emptymatch) {
+ for (i = 0; i < 512; i++) {
+ if (dat[i] == 0xff) continue;
+ emptymatch = 0;
+ break;
+ }
+ /* If emptymatch=1 still, we do have an all-0xff data buffer.
+ Return all-0xff ecc value instead of the computed one, so
+ it'll look just like a freshly-erased page. */
+ if (emptymatch) memset(ecc_code, 0xff, 6);
+ }
return 0;
}
@@ -496,7 +522,8 @@
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = (void *)this->priv;
unsigned long docptr = doc->virtadr;
- volatile char dummy;
+ volatile u_char dummy;
+ int emptymatch = 1;
/* flush the pipeline */
if (DoC_is_2000(doc)) {
@@ -511,13 +538,31 @@
/* Error occured ? */
if (dummy & 0x80) {
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++) {
calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
- ret = doc_decode_ecc (dat, calc_ecc);
+ if (calc_ecc[i] != empty_read_syndrome[i])
+ emptymatch = 0;
+ }
+ if (emptymatch) {
+ for (i = 0; i < 6; i++) {
+ if (read_ecc[i] == 0xff) continue;
+ emptymatch = 0;
+ break;
+ }
+ }
+ /* If emptymatch == 1, this is almost certainly a freshly-
+ erased block, in which case the ECC will not come out right.
+ We'll suppress the error and tell the caller everything's
+ OK. Because it is. */
+ if (!emptymatch) ret = doc_decode_ecc (dat, calc_ecc);
if (ret > 0)
printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
}
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+ if (no_ecc_failures && (ret == -1)) {
+ printk(KERN_ERR "suppressing ECC failure\n");
+ ret = 0;
+ }
return ret;
}
More information about the linux-mtd-cvs
mailing list