mtd: nand: hide in-memory BBT implementation details
authorBrian Norris <computersforpeace@gmail.com>
Wed, 31 Jul 2013 00:52:59 +0000 (17:52 -0700)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Fri, 30 Aug 2013 15:48:17 +0000 (16:48 +0100)
nand_base.c shouldn't have to know the implementation details of
nand_bbt's in-memory BBT. Specifically, nand_base shouldn't perform the
bit masking and shifting to isolate a BBT entry.

Instead, just move some of the BBT code into a new nand_markbad_bbt()
interface. This interface allows external users (i.e., nand_base) to
mark a single block as bad in the BBT. Then nand_bbt will take care of
modifying the in-memory BBT and updating the flash-based BBT (if
applicable).

Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
include/linux/mtd/nand.h

index 5a7467c..9a48758 100644 (file)
@@ -374,22 +374,20 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
  * block table(s) and/or marker(s)). We only allow the hardware driver to
  * specify how to write bad block markers to OOB (chip->block_markbad).
  *
- * We try operations in the following order, according to our bbt_options
- * (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
+ * We try operations in the following order:
  *  (1) erase the affected block, to allow OOB marker to be written cleanly
- *  (2) update in-memory BBT
- *  (3) write bad block marker to OOB area of affected block
- *  (4) update flash-based BBT
- * Note that we retain the first error encountered in (3) or (4), finish the
+ *  (2) write bad block marker to OOB area of affected block (unless flag
+ *      NAND_BBT_NO_OOB_BBM is present)
+ *  (3) update the BBT
+ * Note that we retain the first error encountered in (2) or (3), finish the
  * procedures, and dump the error in the end.
 */
 static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
        struct nand_chip *chip = mtd->priv;
-       int block, res, ret = 0;
-       int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
+       int res, ret = 0;
 
-       if (write_oob) {
+       if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
                struct erase_info einfo;
 
                /* Attempt erase before marking OOB */
@@ -398,24 +396,16 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
                einfo.addr = ofs;
                einfo.len = 1 << chip->phys_erase_shift;
                nand_erase_nand(mtd, &einfo, 0);
-       }
-
-       /* Get block number */
-       block = (int)(ofs >> chip->bbt_erase_shift);
-       /* Mark block bad in memory-based BBT */
-       if (chip->bbt)
-               chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
-       /* Write bad block marker to OOB */
-       if (write_oob) {
+               /* Write bad block marker to OOB */
                nand_get_device(mtd, FL_WRITING);
                ret = chip->block_markbad(mtd, ofs);
                nand_release_device(mtd);
        }
 
-       /* Update flash-based bad block table */
-       if (chip->bbt_options & NAND_BBT_USE_FLASH) {
-               res = nand_update_bbt(mtd, ofs);
+       /* Mark block bad in BBT */
+       if (chip->bbt) {
+               res = nand_markbad_bbt(mtd, ofs);
                if (!ret)
                        ret = res;
        }
index bac481a..ae3fb58 100644 (file)
@@ -79,6 +79,8 @@
 #define BBT_ENTRY_MASK         0x03
 #define BBT_ENTRY_SHIFT                2
 
+static int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+
 static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
 {
        uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
@@ -1194,13 +1196,13 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 }
 
 /**
- * nand_update_bbt - [NAND Interface] update bad block table(s)
+ * nand_update_bbt - update bad block table(s)
  * @mtd: MTD device structure
  * @offs: the offset of the newly marked block
  *
  * The function updates the bad block table(s).
  */
-int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
+static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
        struct nand_chip *this = mtd->priv;
        int len, res = 0;
@@ -1390,5 +1392,27 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
        return 1;
 }
 
+/**
+ * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
+ * @mtd: MTD device structure
+ * @offs: offset of the bad block
+ */
+int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
+{
+       struct nand_chip *this = mtd->priv;
+       int block, ret = 0;
+
+       block = (int)(offs >> this->bbt_erase_shift);
+
+       /* Mark bad block in memory */
+       bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+
+       /* Update flash-based bad block table */
+       if (this->bbt_options & NAND_BBT_USE_FLASH)
+               ret = nand_update_bbt(mtd, offs);
+
+       return ret;
+}
+
 EXPORT_SYMBOL(nand_scan_bbt);
 EXPORT_SYMBOL(nand_default_bbt);
index 0745a42..9f7b248 100644 (file)
@@ -628,8 +628,8 @@ extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
 extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
 extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
                           int allowbbt);