tree c5d3cdffbfc11ec2ee82d64aef4177e92dfdffc7
parent 41ce921440bd14d9b69b19fbf47d9278582739fe
author Artem B. Bityuckiy <[EMAIL PROTECTED]> Fri, 11 Feb 2005 10:14:15 +0000
committer Thomas Gleixner <[EMAIL PROTECTED]> Mon, 23 May 2005 12:32:18 +0200

[MTD] NAND: Read only OOB bytes during bad block scan

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.

Fix debugging message.

Signed-off-by: Artem B. Bityuckiy <[EMAIL PROTECTED]>
Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>

 drivers/mtd/nand/nand_bbt.c |   52 ++++++++++++++++++++++++++++++++------------
 1 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -6,7 +6,7 @@
  *   
  *  Copyright (C) 2004 Thomas Gleixner ([EMAIL PROTECTED])
  *
- * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $
+ * $Id: nand_bbt.c,v 1.30 2005/02/11 10:14:12 dedekind Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -252,10 +252,10 @@ static int read_abs_bbts (struct mtd_inf
  * 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 @@ static void create_bbt (struct mtd_info 
                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 @@ static void create_bbt (struct mtd_info 
                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 @@ static void create_bbt (struct mtd_info 
        }
        
        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 @@ static void create_bbt (struct mtd_info 
                i += 2;
                from += (1 << this->bbt_erase_shift);
        }
+       return 0;
 }
 
 /**
@@ -595,8 +614,7 @@ static int nand_memory_bbt (struct mtd_i
 
        /* 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 @@ int nand_scan_bbt (struct mtd_info *mtd,
        /* 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);
@@ -1042,7 +1066,7 @@ int nand_isbad_bbt (struct mtd_info *mtd
        res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
        DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: 
(block %d) 0x%02x\n", 
-               (unsigned int)offs, res, block >> 1);
+               (unsigned int)offs, block >> 1, res);
 
        switch ((int)res) {
        case 0x00:      return 0;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to