[RESEND PATCH] mtd: nand: nand_bbt: scan for next free bbt block if writing bbt fails

Jeff Westfahl jeff.westfahl at ni.com
Thu May 16 09:35:41 EDT 2013


If erasing or writing the BBT fails, we should mark the current BBT block
as bad and use the BBT descriptor to scan for the next available unused
block in the BBT. We should only return a failure if there isn't any space
left.

Signed-off-by: Jeff Westfahl <jeff.westfahl at ni.com>
---
 drivers/mtd/nand/nand_bbt.c |   21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 2672643..900bda1 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -697,6 +697,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t 
*buf,
                        page = td->pages[chip];
                        goto write;
                }
+       next:
 
                /*
                 * Automatic placement of the bad block table. Search 
direction
@@ -831,14 +832,26 @@ static int write_bbt(struct mtd_info *mtd, uint8_t 
*buf,
                einfo.addr = to;
                einfo.len = 1 << this->bbt_erase_shift;
                res = nand_erase_nand(mtd, &einfo, 1);
-               if (res < 0)
-                       goto outerr;
+               if (res < 0) {
+                       /* This block is bad. Mark it as such and see if 
there's
+                          another available in the BBT area. */
+                       int block = page >>
+                               (this->bbt_erase_shift - 
this->page_shift);
+                       this->bbt[block >> 2] |= 0x01 << ((block & 0x03) 
<< 1);
+                       goto next;
+               }
 
                res = scan_write_bbt(mtd, to, len, buf,
                                td->options & NAND_BBT_NO_OOB ? NULL :
                                &buf[len]);
-               if (res < 0)
-                       goto outerr;
+               if (res < 0) {
+                       /* This block is bad. Mark it as such and see if 
there's
+                          another available in the BBT area. */
+                       int block = page >>
+                               (this->bbt_erase_shift - 
this->page_shift);
+                       this->bbt[block >> 2] |= 0x01 << ((block & 0x03) 
<< 1);
+                       goto next;
+               }
 
                pr_info("Bad block table written to 0x%012llx, version 
0x%02X\n",
                         (unsigned long long)to, td->version[chip]);
-- 
1.7.10




More information about the linux-mtd mailing list