mtd/drivers/mtd nftlcore.c,1.95,1.96 nftlmount.c,1.35,1.36

dbrown at infradead.org dbrown at infradead.org
Mon Jun 28 09:52:58 EDT 2004


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

Modified Files:
	nftlcore.c nftlmount.c 
Log Message:
Modified to work with new NAND-based DiskOnChip driver.  No longer works with the older drivers!


Index: nftlcore.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nftlcore.c,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -r1.95 -r1.96
--- nftlcore.c	16 Jun 2004 19:21:17 -0000	1.95
+++ nftlcore.c	28 Jun 2004 13:52:55 -0000	1.96
@@ -43,9 +43,19 @@
 	struct NFTLrecord *nftl;
 	unsigned long temp;
 
-	if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
+	if (mtd->type != MTD_NANDFLASH)
+		return;
+	/* OK, this is moderately ugly.  But probably safe.  Alternatives? */
+	if (memcmp(mtd->name, "DiskOnChip", 10))
 		return;
 
+	if (!mtd->block_isbad) {
+		printk(KERN_ERR
+"NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
+"Please use the new diskonchip driver under the NAND subsystem.\n");
+		return;
+	}
+
 	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
 
 	nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
@@ -60,6 +70,8 @@
 	nftl->mbd.devnum = -1;
 	nftl->mbd.blksize = 512;
 	nftl->mbd.tr = tr;
+	memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
+	nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
         if (NFTL_mount(nftl) < 0) {
 		printk(KERN_WARNING "NFTL: could not mount device\n");
@@ -350,17 +362,19 @@
                 if (BlockMap[block] == BLOCK_NIL)
                         continue;
                 
-                ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
-				  512, &retlen, movebuf, (char *)&oob, NULL); 
+                ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
+				  512, &retlen, movebuf); 
                 if (ret < 0) {
-                    ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
+                    ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
                                       + (block * 512), 512, &retlen,
-                                      movebuf, (char *)&oob, NULL); 
+                                      movebuf); 
                     if (ret != -EIO) 
                         printk("Error went away on retry.\n");
                 }
+		memset(&oob, 0xff, sizeof(struct nftl_oob));
+		oob.b.Status = oob.b.Status1 = SECTOR_USED;
                 MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
-                             512, &retlen, movebuf, (char *)&oob, NULL);
+                             512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);
 	}
         
         /* add the header so that it is now a valid chain */
@@ -390,7 +404,6 @@
 
                 if (NFTL_formatblock(nftl, thisEUN) < 0) {
 			/* could not erase : mark block as reserved
-			 * FixMe: Update Bad Unit Table on disk
 			 */
 			nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
                 } else {
@@ -617,7 +630,7 @@
 	u16 writeEUN;
 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
 	size_t retlen;
-	u8 eccbuf[6];
+	struct nftl_oob oob;
 
 	writeEUN = NFTL_findwriteunit(nftl, block);
 
@@ -628,9 +641,11 @@
 		return 1;
 	}
 
+	memset(&oob, 0xff, sizeof(struct nftl_oob));
+	oob.b.Status = oob.b.Status1 = SECTOR_USED;
 	MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
-		     512, &retlen, (char *)buffer, (char *)eccbuf, NULL);
-        /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */
+		     512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo);
+        /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
 
 	return 0;
 }
@@ -692,8 +707,7 @@
 	} else {
 		loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
 		size_t retlen;
-		u_char eccbuf[6];
-		if (MTD_READECC(nftl->mbd.mtd, ptr, 512, &retlen, buffer, eccbuf, NULL))
+		if (MTD_READ(nftl->mbd.mtd, ptr, 512, &retlen, buffer))
 			return -EIO;
 	}
 	return 0;

Index: nftlmount.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nftlmount.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- nftlmount.c	16 Jun 2004 19:21:17 -0000	1.35
+++ nftlmount.c	28 Jun 2004 13:52:55 -0000	1.36
@@ -50,6 +50,10 @@
 
         /* Assume logical EraseSize == physical erasesize for starting the scan. 
 	   We'll sort it out later if we find a MediaHeader which says otherwise */
+	/* Actually, we won't.  The new DiskOnChip driver has already scanned
+	   the MediaHeader and adjusted the virtual erasesize it presents in
+	   the mtd device accordingly.  We could even get rid of
+	   nftl->EraseSize if there were any point in doing so. */
 	nftl->EraseSize = nftl->mbd.mtd->erasesize;
         nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
 
@@ -62,7 +66,10 @@
 
 		/* Check for ANAND header first. Then can whinge if it's found but later
 		   checks fail */
-		if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) {
+		ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
+		/* We ignore ret in case the ECC of the MediaHeader is invalid
+		   (which is apparently acceptable) */
+		if (retlen != SECTORSIZE) {
 			static int warncount = 5;
 
 			if (warncount) {
@@ -149,6 +156,10 @@
 		memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
 
 		/* Do some sanity checks on it */
+#if 0
+The new DiskOnChip driver scans the MediaHeader itself, and presents a virtual
+erasesize based on UnitSizeFactor.  So the erasesize we read from the mtd
+device is already correct.
 		if (mh->UnitSizeFactor == 0) {
 			printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
 		} else if (mh->UnitSizeFactor < 0xfc) {
@@ -161,6 +172,7 @@
 			nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
 			nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
 		}
+#endif
 		nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
 		if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
 			printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
@@ -213,6 +225,8 @@
 
 		/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
 		for (i = 0; i < nftl->nb_blocks; i++) {
+#if 0
+The new DiskOnChip driver already scanned the bad block table.  Just query it.
 			if ((i & (SECTORSIZE - 1)) == 0) {
 				/* read one sector for every SECTORSIZE of blocks */
 				if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
@@ -228,6 +242,9 @@
 			/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
 			if (buf[i & (SECTORSIZE - 1)] != 0xff)
 				nftl->ReplUnitTable[i] = BLOCK_RESERVED;
+#endif
+			if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
+				nftl->ReplUnitTable[i] = BLOCK_RESERVED;
 		}
 		
 		nftl->MediaUnit = block;
@@ -253,21 +270,16 @@
 			      int check_oob)
 {
 	int i, retlen;
-	u8 buf[SECTORSIZE];
+	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
 
 	for (i = 0; i < len; i += SECTORSIZE) {
-		/* we want to read the sector without ECC check here since a free
-		   sector does not have ECC syndrome on it yet */
-		if (MTD_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
+		if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
 			return -1;
 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
 			return -1;
 
 		if (check_oob) {
-			if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize,
-					&retlen, buf) < 0)
-				return -1;
-			if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0)
+			if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
 				return -1;
 		}
 		address += SECTORSIZE;
@@ -282,7 +294,6 @@
  * Return: 0 when succeed, -1 on error.
  *
  *  ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 
- *        2. UnitSizeFactor != 0xFF
  */
 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
 {
@@ -312,11 +323,10 @@
 	MTD_ERASE(nftl->mbd.mtd, instr);
 
 	if (instr->state == MTD_ERASE_FAILED) {
-		/* could not format, FixMe: We should update the BadUnitTable 
-		   both in memory and on disk */
 		printk("Error while formatting block %d\n", block);
-		return -1;
-	} else {
+		goto fail;
+	}
+
 		/* increase and write Wear-Leveling info */
 		nb_erases = le32_to_cpu(uci.WearInfo);
 		nb_erases++;
@@ -329,14 +339,18 @@
 		 * FixMe:  is this check really necessary ? since we have check the
 		 *         return code after the erase operation. */
 		if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
-			return -1;
+			goto fail;
 
 		uci.WearInfo = le32_to_cpu(nb_erases);
 		if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
 				 &retlen, (char *)&uci) < 0)
-			return -1;
+			goto fail;
 		return 0;
-	}
+fail:
+	/* could not format, update the bad block table (caller is responsible
+	   for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
+	nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
+	return -1;
 }
 
 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
@@ -441,8 +455,7 @@
 
 		printk("Formatting block %d\n", block);
 		if (NFTL_formatblock(nftl, block) < 0) {
-			/* cannot format !!!! Mark it as Bad Unit,
-			   FixMe: update the BadUnitTable on disk */
+			/* cannot format !!!! Mark it as Bad Unit */
 			nftl->ReplUnitTable[block] = BLOCK_RESERVED;
 		} else {
 			nftl->ReplUnitTable[block] = BLOCK_FREE;





More information about the linux-mtd-cvs mailing list