mtd/drivers/mtd inftlmount.c,1.12,1.13 inftlcore.c,1.14,1.15

dbrown at infradead.org dbrown at infradead.org
Mon Jun 28 12:06:38 EDT 2004


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

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


Index: inftlmount.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/inftlmount.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- inftlmount.c	26 Jun 2003 07:31:36 -0000	1.12
+++ inftlmount.c	28 Jun 2004 16:06:36 -0000	1.13
@@ -54,7 +54,7 @@
 {
 	struct inftl_unittail h1;
 	//struct inftl_oob oob;
-	unsigned int i, block, boot_record_count = 0;
+	unsigned int i, block;
 	u8 buf[SECTORSIZE];
 	struct INFTLMediaHeader *mh = &inftl->MediaHdr;
 	struct INFTLPartition *ip;
@@ -72,7 +72,6 @@
         inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
 
 	inftl->MediaUnit = BLOCK_NIL;
-	inftl->SpareMediaUnit = BLOCK_NIL;
 
 	/* Search for a valid boot record */
 	for (block = 0; block < inftl->nb_blocks; block++) {
@@ -82,8 +81,11 @@
 		 * Check for BNAND header first. Then whinge if it's found
 		 * but later checks fail.
 		 */
-		if ((ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize,
-		    SECTORSIZE, &retlen, buf))) {
+		ret = MTD_READ(inftl->mbd.mtd, block * inftl->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) {
@@ -114,36 +116,28 @@
 			continue;
 		}
 
-		if (boot_record_count) {
-			/*
-			 * We've already processed one. So we just check if
-			 * this one is the same as the first one we found.
-			 */
-			if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
-				printk(KERN_WARNING "INFTL: Media Headers at "
-					"0x%x and 0x%x disagree.\n",
-					inftl->MediaUnit * inftl->EraseSize,
-					block * inftl->EraseSize);
-				return -1;
-			}
-			if (boot_record_count == 1)
-				inftl->SpareMediaUnit = block;
-
-			/*
-			 * Mark this boot record (INFTL MediaHeader) block as
-			 * reserved.
-			 */
-			inftl->PUtable[block] = BLOCK_RESERVED;
-
-			boot_record_count++;
-			continue;
-		}
 
 		/*
 		 * This is the first we've seen.
 		 * Copy the media header structure into place.
 		 */
 		memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
+
+		/* Read the spare media header at offset 4096 */
+		MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize + 4096,
+		    SECTORSIZE, &retlen, buf);
+		if (retlen != SECTORSIZE) {
+			printk(KERN_WARNING "INFTL: Unable to read spare "
+			       "Media Header\n");
+			return -1;
+		}
+		/* Check if this one is the same as the first one we found. */
+		if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
+			printk(KERN_WARNING "INFTL: Primary and spare Media "
+			       "Headers disagree.\n");
+			return -1;
+		}
+
 		mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
 		mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
 		mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
@@ -197,8 +191,9 @@
 				"UnitSizeFactor 0x%02x is experimental\n",
 				mh->BlockMultiplierBits);
 			inftl->EraseSize = inftl->mbd.mtd->erasesize <<
-				(0xff - mh->BlockMultiplierBits);
+				mh->BlockMultiplierBits;
 			inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
+			block >>= mh->BlockMultiplierBits;
 		}
 
 		/* Scan the partitions */
@@ -317,34 +312,23 @@
 		/* Mark this boot record (NFTL MediaHeader) block as reserved */
 		inftl->PUtable[block] = BLOCK_RESERVED;
 
-#if 0
 		/* Read Bad Erase Unit Table and modify PUtable[] accordingly */
 		for (i = 0; i < inftl->nb_blocks; i++) {
-			if ((i & (SECTORSIZE - 1)) == 0) {
-				/* read one sector for every SECTORSIZE of blocks */
-				if ((ret = MTD_READECC(inftl->mbd.mtd,
-				    block * inftl->EraseSize + i + SECTORSIZE,
-				    SECTORSIZE, &retlen, buf,
-				    (char *)&oob, NULL)) < 0) {
-					printk(KERN_WARNING "INFTL: read of "
-						"bad sector table failed "
-						"(err %d)\n", ret);
-					kfree(inftl->VUtable);
-					kfree(inftl->PUtable);
-					return -1;
-				}
+			int physblock;
+			/* If any of the physical eraseblocks are bad, don't
+			   use the unit. */
+			for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
+				if (inftl->mbd.mtd->block_isbad(inftl->mbd.mtd, i * inftl->EraseSize + physblock))
+					inftl->PUtable[i] = BLOCK_RESERVED;
 			}
-			/* Mark the Bad Erase Unit as RESERVED in PUtable */
-			if (buf[i & (SECTORSIZE - 1)] != 0xff)
-				inftl->PUtable[i] = BLOCK_RESERVED;
 		}
-#endif
 
 		inftl->MediaUnit = block;
-		boot_record_count++;
+		return 0;
 	}
-		
-	return boot_record_count ? 0 : -1;
+
+	/* Not found. */
+	return -1;
 }
 
 static int memcmpb(void *a, int c, int n)
@@ -365,27 +349,20 @@
 	int len, int check_oob)
 {
 	int i, retlen;
-	u8 buf[SECTORSIZE];
+	u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=0x%x,"
 		"address=0x%x,len=%d,check_oob=%d)\n", (int)inftl,
 		address, len, check_oob);
 
 	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(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
+		if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0)
 			return -1;
 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
 			return -1;
 
 		if (check_oob) {
-			if (MTD_READOOB(inftl->mbd.mtd, address,
-			    inftl->mbd.mtd->oobsize, &retlen, buf) < 0)
-				return -1;
-			if (memcmpb(buf, 0xff, inftl->mbd.mtd->oobsize) != 0)
+			if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0)
 				return -1;
 		}
 		address += SECTORSIZE;
@@ -402,13 +379,13 @@
  * Return: 0 when succeed, -1 on error.
  *
  * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 
- *       2. UnitSizeFactor != 0xFF
  */
 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
 {
 	int retlen;
 	struct inftl_unittail uci;
 	struct erase_info *instr = &inftl->instr;
+	int physblock;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=0x%x,"
 		"block=%d)\n", (int)inftl, block);
@@ -420,37 +397,44 @@
 
 	/* Use async erase interface, test return code */
 	instr->addr = block * inftl->EraseSize;
-	instr->len = inftl->EraseSize;
-	MTD_ERASE(inftl->mbd.mtd, instr);
+	instr->len = inftl->mbd.mtd->erasesize;
+	/* Erase one physical eraseblock at a time, even though the NAND api
+	   allows us to group them.  This way we if we have a failure, we can
+	   mark only the failed block in the bbt. */
+	for (physblock = 0; physblock < inftl->EraseSize; physblock += instr->len, instr->addr += instr->len) {
+		MTD_ERASE(inftl->mbd.mtd, instr);
+
+		if (instr->state == MTD_ERASE_FAILED) {
+			printk(KERN_WARNING "INFTL: error while formatting block %d\n",
+				block);
+			goto fail;
+		}
 
-	if (instr->state == MTD_ERASE_FAILED) {
 		/*
-		 * Could not format, FixMe: We should update the BadUnitTable 
-		 * both in memory and on disk.
-		 */
-		printk(KERN_WARNING "INFTL: error while formatting block %d\n",
-			block);
-		return -1;
+	 	* Check the "freeness" of Erase Unit before updating metadata.
+	 	* FixMe: is this check really necessary? Since we have check the
+	 	*        return code after the erase operation.
+	 	*/
+		if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
+			goto fail;
 	}
 
-	/*
-	 * Check the "freeness" of Erase Unit before updating metadata.
-	 * FixMe: is this check really necessary? Since we have check the
-	 *        return code after the erase operation.
-	 */
-	if (check_free_sectors(inftl, instr->addr, inftl->EraseSize, 1) != 0)
-		return -1;
-
 	uci.EraseMark = cpu_to_le16(ERASE_MARK);
 	uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
 	uci.Reserved[0] = 0;
 	uci.Reserved[1] = 0;
 	uci.Reserved[2] = 0;
 	uci.Reserved[3] = 0;
-	if (MTD_WRITEOOB(inftl->mbd.mtd, block * inftl->EraseSize + SECTORSIZE * 2 +
+	instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
+	if (MTD_WRITEOOB(inftl->mbd.mtd, instr->addr +
 	    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 PUtable to BLOCK_RESERVED on failure) */
+	inftl->mbd.mtd->block_markbad(inftl->mbd.mtd, instr->addr);
+	return -1;
 }
 
 /*
@@ -475,7 +459,6 @@
 		if (INFTL_formatblock(inftl, block) < 0) {
 			/*
 			 * Cannot format !!!! Mark it as Bad Unit,
-			 * FixMe: update the BadUnitTable on disk.
 			 */
 			inftl->PUtable[block] = BLOCK_RESERVED;
 		} else {

Index: inftlcore.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/inftlcore.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- inftlcore.c	26 Jun 2003 08:28:26 -0000	1.14
+++ inftlcore.c	28 Jun 2004 16:06:36 -0000	1.15
@@ -55,9 +55,19 @@
 	struct INFTLrecord *inftl;
 	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
+"INFTL 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_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
 
 	inftl = kmalloc(sizeof(*inftl), GFP_KERNEL);
@@ -72,6 +82,8 @@
 	inftl->mbd.devnum = -1;
 	inftl->mbd.blksize = 512;
 	inftl->mbd.tr = tr;
+	memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
+	inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
         if (INFTL_mount(inftl) < 0) {
 		printk(KERN_WARNING "INFTL: could not mount device\n");
@@ -284,21 +296,22 @@
                 if (BlockMap[block] == BLOCK_NIL)
                         continue;
                 
-                ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize *
+                ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
 			BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
-			&retlen, movebuf, (char *)&oob, NULL); 
+			&retlen, movebuf); 
                 if (ret < 0) {
-			ret = MTD_READECC(inftl->mbd.mtd, (inftl->EraseSize *
+			ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
 				BlockMap[block]) + (block * SECTORSIZE),
-				SECTORSIZE, &retlen, movebuf, (char *)&oob,
-				NULL); 
+				SECTORSIZE, &retlen, movebuf);
 			if (ret != -EIO) 
                         	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
 					"away on retry?\n");
                 }
+                memset(&oob, 0xff, sizeof(struct inftl_oob));
+                oob.b.Status = oob.b.Status1 = SECTOR_USED;
                 MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
 			(block * SECTORSIZE), SECTORSIZE, &retlen,
-			movebuf, (char *)&oob, NULL);
+			movebuf, (char *)&oob, &inftl->oobinfo);
 	}
 
 	/*
@@ -326,7 +339,6 @@
                 if (INFTL_formatblock(inftl, thisEUN) < 0) {
 			/*
 			 * Could not erase : mark block as reserved.
-			 * FixMe: Update Bad Unit Table on disk.
 			 */
 			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
                 } else {
@@ -668,7 +680,6 @@
                 if (INFTL_formatblock(inftl, thisEUN) < 0) {
 			/*
 			 * Could not erase : mark block as reserved.
-			 * FixMe: Update Bad Unit Table on medium.
 			 */
 			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
                 } else {
@@ -754,7 +765,7 @@
 	unsigned int writeEUN;
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
 	size_t retlen;
-	u8 eccbuf[6];
+	struct inftl_oob oob;
 	char *p, *pend;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=0x%x,block=%d,"
@@ -778,11 +789,13 @@
 			return 1;
 		}
 
+		memset(&oob, 0xff, sizeof(struct inftl_oob));
+		oob.b.Status = oob.b.Status1 = SECTOR_USED;
 		MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
 			blockofs, SECTORSIZE, &retlen, (char *)buffer,
-			(char *)eccbuf, NULL);
+			(char *)&oob, &inftl->oobinfo);
 		/*
-		 * No need to write SECTOR_USED flags since they are written
+		 * need to write SECTOR_USED flags since they are not written
 		 * in mtd_writeecc
 		 */
 	} else {
@@ -846,9 +859,8 @@
 	} else {
         	size_t retlen;
 		loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
-		u_char eccbuf[6];
-		if (MTD_READECC(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
-		    buffer, eccbuf, NULL))
+		if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
+		    buffer))
 			return -EIO;
 	}
 	return 0;





More information about the linux-mtd-cvs mailing list