]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/onenand/onenand_bbt.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6-omap-h63xx.git] / drivers / mtd / onenand / onenand_bbt.c
index 4510d3361eaa82f77ddca510bb4fa460a26cb3f1..aecdd50a1781354556c9948ed86b4a1f09e52c36 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
+extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+                               struct mtd_oob_ops *ops);
+
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf          the buffer to search
@@ -62,10 +65,11 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        int startblock;
        loff_t from;
        size_t readlen, ooblen;
+       struct mtd_oob_ops ops;
 
        printk(KERN_INFO "Scanning device for bad blocks\n");
 
-       len = 1;
+       len = 2;
 
        /* We need only read few bytes from the OOB area */
        scanlen = ooblen = 0;
@@ -79,24 +83,28 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        startblock = 0;
        from = 0;
 
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooblen = readlen;
+       ops.oobbuf = buf;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
        for (i = startblock; i < numblocks; ) {
                int ret;
 
                for (j = 0; j < len; j++) {
-                       size_t retlen;
-
                        /* No need to read pages fully,
                         * just read required OOB bytes */
-                       ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,
-                                               readlen, &retlen, &buf[0]);
+                       ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
 
-                       if (ret)
-                               return ret;
+                       /* If it is a initial bad block, just ignore it */
+                       if (ret == ONENAND_BBT_READ_FATAL_ERROR)
+                               return -EIO;
 
-                       if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+                       if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
                                bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
                                printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
                                        i >> 1, (unsigned int) from);
+                               mtd->ecc_stats.badblocks++;
                                break;
                        }
                }
@@ -163,8 +171,8 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
  * marked good / bad blocks and writes the bad block table(s) to
  * the selected place.
  *
- * The bad block table memory is allocated here. It must be freed
- * by calling the onenand_free_bbt function.
+ * The bad block table memory is allocated here. It is freed
+ * by the onenand_release function.
  *
  */
 int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
@@ -174,14 +182,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
        int len, ret = 0;
 
        len = mtd->size >> (this->erase_shift + 2);
-       /* Allocate memory (2bit per block) */
-       bbm->bbt = kmalloc(len, GFP_KERNEL);
+       /* Allocate memory (2bit per block) and clear the memory bad block table */
+       bbm->bbt = kzalloc(len, GFP_KERNEL);
        if (!bbm->bbt) {
                printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
                return -ENOMEM;
        }
-       /* Clear the memory bad block table */
-       memset(bbm->bbt, 0x00, len);
 
        /* Set the bad block position */
        bbm->badblockpos = ONENAND_BADBLOCK_POS;
@@ -227,14 +233,12 @@ int onenand_default_bbt(struct mtd_info *mtd)
        struct onenand_chip *this = mtd->priv;
        struct bbm_info *bbm;
 
-       this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL);
+       this->bbm = kzalloc(sizeof(struct bbm_info), GFP_KERNEL);
        if (!this->bbm)
                return -ENOMEM;
 
        bbm = this->bbm;
 
-       memset(bbm, 0, sizeof(struct bbm_info));
-
        /* 1KB page has same configuration as 2KB page */
        if (!bbm->badblock_pattern)
                bbm->badblock_pattern = &largepage_memorybased;