mtd/drivers/mtd/nand nand_base.c,1.155,1.156

tpoynor at infradead.org tpoynor at infradead.org
Fri Nov 18 18:12:36 EST 2005


Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv23133/drivers/mtd/nand

Modified Files:
	nand_base.c 
Log Message:
[MTD] NAND: Fix truncated OOB writes

The nand-layout-based code does not properly write ECC bytes to OOB when
NAND_HWECC_SYNDROME option is not set.  Cleaned up some ambiguous variable
names.  Fix problems on flashes with 40 bytes of ecc / page.

From: Vitaly Wool and Todd Poynor
Signed-off-by: Todd Poynor <tpoynor at mvista.com>


Index: nand_base.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand_base.c,v
retrieving revision 1.155
retrieving revision 1.156
diff -u -r1.155 -r1.156
--- nand_base.c	14 Nov 2005 06:45:25 -0000	1.155
+++ nand_base.c	18 Nov 2005 23:12:31 -0000	1.156
@@ -893,8 +893,8 @@
 static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
 	u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached)
 {
-	int 	i, status;
-	u_char	ecc_code[32];
+	int 	i, oobidx, status;
+	u_char	ecc_code[40];
 	int	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
 	int  	*oob_config = oobsel->eccpos;
 	int	datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
@@ -927,8 +927,8 @@
 		break;
 	default:
 		eccbytes = this->eccbytes;
-		for (i = 0; eccsteps; eccsteps--) {
-			int j = 0, last_datidx = datidx, last_i = i;
+		for (oobidx = 0; eccsteps; eccsteps--) {
+			int j = 0, last_datidx = datidx, last_oobidx;
 			for (; this->layout[j].length; j++) {
 				switch (this->layout[j].type) {
 				case ITEM_TYPE_DATA:
@@ -938,19 +938,15 @@
 					break;
 				case ITEM_TYPE_ECC:
 					this->enable_hwecc(mtd, NAND_ECC_WRITESYN);
-					this->calculate_ecc(mtd, &this->data_poi[last_datidx], &ecc_code[i]);
-					for (; i < last_i + this->layout[j].length; i++, eccidx++)
-						oob_buf[oob_config[eccidx]] = ecc_code[i];
-					/* If the hardware ecc provides syndromes then
-					 * the ecc code must be written immidiately after
-					 * the data bytes (words) */
-					if (this->options & NAND_HWECC_SYNDROME)
-						this->write_buf(mtd, ecc_code, this->layout[j].length);
+					this->calculate_ecc(mtd, &this->data_poi[last_datidx], &ecc_code[eccidx]);
+					for (last_oobidx = oobidx; oobidx < last_oobidx + this->layout[j].length; oobidx++, eccidx++)
+						oob_buf[oobidx] = ecc_code[eccidx];
+					this->write_buf(mtd, ecc_code, this->layout[j].length);
 					break;
 				case ITEM_TYPE_OOB:
 					this->enable_hwecc(mtd, NAND_ECC_WRITEOOB);
-					this->write_buf(mtd, &oob_buf[i], this->layout[j].length);
-					i += this->layout[j].length;
+					this->write_buf(mtd, &oob_buf[oobidx], this->layout[j].length);
+					oobidx += this->layout[j].length;
 					break;
 				}
 			}
@@ -1157,7 +1153,7 @@
 {
 
 	int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
-	int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
+	int read = 0, oob = 0, oobidx, ecc_status = 0, ecc_failed = 0, eccidx;
 	struct nand_chip *this = mtd->priv;
 	u_char *data_poi, *oob_data = oob_buf;
 	u_char ecc_calc[32];
@@ -1269,8 +1265,8 @@
 			break;
 
 		default:
-			for (i = 0, datidx = 0; eccsteps; eccsteps--) {
-				int last_datidx = datidx, last_i = i;
+			for (oobidx = 0, datidx = 0, eccidx = 0; eccsteps; eccsteps--) {
+				int last_datidx = datidx, last_oobidx = oobidx;
 				for (j = 0; this->layout[j].length; j++) {
 					switch (this->layout[j].type) {
 					case ITEM_TYPE_DATA:
@@ -1284,30 +1280,28 @@
 						DEBUG (MTD_DEBUG_LEVEL3, "%s: reading %d ecc bytes\n", __FUNCTION__, this->layout[j].length);
 						/* let the particular driver decide whether to read ECC */
 						this->enable_hwecc(mtd, NAND_ECC_READSYN);
-						this->read_buf(mtd, &oob_data[i], this->layout[j].length);
+						this->read_buf(mtd, &oob_data[oobidx], this->layout[j].length);
 						if (!compareecc) {
-
 							/* We calc error correction directly, it checks the hw
 							 * generator for an error, reads back the syndrome and
 							 * does the error correction on the fly */
-							ecc_status = this->correct_data(mtd, &data_poi[last_datidx], &oob_data[last_i], &ecc_code[last_i]);
+							ecc_status = this->correct_data(mtd, &data_poi[last_datidx], &oob_data[last_oobidx], &ecc_code[eccidx]);
 							if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
 								DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
 									"Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
 								ecc_failed++;
 							}
-							i += this->layout[j].length;
-						} else {
-							this->calculate_ecc(mtd, &data_poi[last_datidx], &ecc_calc[last_i]);
-							i += this->layout[j].length;
-						}
+						} else
+							this->calculate_ecc(mtd, &data_poi[last_datidx], &ecc_calc[eccidx]);
+						oobidx += this->layout[j].length;
+						eccidx += this->layout[j].length;
 						break;
 					case ITEM_TYPE_OOB:
 						DEBUG (MTD_DEBUG_LEVEL3, "%s: reading %d free oob bytes\n", __FUNCTION__, this->layout[j].length);
 						this->enable_hwecc(mtd, NAND_ECC_READOOB);
 
-						this->read_buf(mtd, &oob_data[i], this->layout[j].length);
-						i += this->layout[j].length;
+						this->read_buf(mtd, &oob_data[oobidx], this->layout[j].length);
+						oobidx += this->layout[j].length;
 						break;
 					}
 				}





More information about the linux-mtd-cvs mailing list