mtd/drivers/mtd/nand nand_bbt.c,1.28,1.29

Artem Bityuckiy dedekind at infradead.org
Thu Feb 10 14:10:08 EST 2005


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

Modified Files:
	nand_bbt.c 
Log Message:
When scanning NAND for bad blocks, don't read the whole page, read only needed OOB bytes instead. Also check the return code of the nand_read_raw() function. Correctly free the this->bbt array in case of failure. Tested with Large page NAND.


Index: nand_bbt.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand_bbt.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- nand_bbt.c	13 Nov 2004 10:19:09 -0000	1.28
+++ nand_bbt.c	10 Feb 2005 19:10:05 -0000	1.29
@@ -252,10 +252,10 @@
  * Create a bad block table by scanning the device
  * for the given good/bad block identify pattern
  */
-static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
+static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
 {
 	struct nand_chip *this = mtd->priv;
-	int i, j, numblocks, len, scanlen;
+	int i, j, numblocks, len, scanlen, pagelen;
 	int startblock;
 	loff_t from;
 	size_t readlen, ooblen;
@@ -270,9 +270,18 @@
 		else	
 			len = 1;
 	}
-	scanlen	= mtd->oobblock + mtd->oobsize;
-	readlen = len * mtd->oobblock;
-	ooblen = len * mtd->oobsize;
+	
+	if (bd->options == 0) {
+		/* Memory-based BBT. We may read only needed bytes from the OOB area to
+		 * test if block is bad, no need to read the whole page content. */
+		scanlen	= ooblen = pagelen = 0;
+		readlen = bd->len;
+	} else {
+		scanlen	= mtd->oobblock + mtd->oobsize;
+		readlen = len * mtd->oobblock;
+		ooblen = len * mtd->oobsize;
+		pagelen = mtd->oobblock;
+	}
 
 	if (chip == -1) {
 		/* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
@@ -284,7 +293,7 @@
 		if (chip >= this->numchips) {
 			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
 				chip + 1, this->numchips);
-			return;	
+			return -EINVAL;	
 		}
 		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
 		startblock = chip * numblocks;
@@ -293,9 +302,18 @@
 	}
 	
 	for (i = startblock; i < numblocks;) {
-		nand_read_raw (mtd, buf, from, readlen, ooblen);
+		int ret;
+		
+		if (bd->options == 0) {
+			size_t retlen;
+			if ((ret = mtd->read_oob(mtd, from + bd->offs, bd->len, &retlen, &buf[bd->offs])))
+				return ret;
+		} else {
+			if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))
+				return ret;
+		}
 		for (j = 0; j < len; j++) {
-			if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+			if (check_pattern (&buf[j * scanlen], scanlen, pagelen, bd)) {
 				this->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 
 					i >> 1, (unsigned int) from);
@@ -305,6 +323,7 @@
 		i += 2;
 		from += (1 << this->bbt_erase_shift);
 	}
+	return 0;
 }
 
 /**
@@ -595,8 +614,7 @@
 
 	/* Ensure that we only scan for the pattern and nothing else */
 	bd->options = 0;
-	create_bbt (mtd, this->data_buf, bd, -1);
-	return 0;
+	return create_bbt (mtd, this->data_buf, bd, -1);
 }
 
 /**
@@ -808,8 +826,14 @@
 	/* If no primary table decriptor is given, scan the device
 	 * to build a memory based bad block table
 	 */
-	if (!td)
-		return nand_memory_bbt(mtd, bd);
+	if (!td) {
+		if ((res = nand_memory_bbt(mtd, bd))) {
+			printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			kfree (this->bbt);
+			this->bbt = NULL;
+		}
+		return res;
+	}
 
 	/* Allocate a temporary buffer for one eraseblock incl. oob */
 	len = (1 << this->bbt_erase_shift);





More information about the linux-mtd-cvs mailing list