aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2013-07-30 20:52:59 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:06:00 -0400
commitfe9ec6f282ae68ee2b634189906d6f79f480e46d (patch)
treec0ccb00f43b2f1381f1ea558bcf3f0a557273389
parent62801eed490bb10ea7203191d1e8626c33e9f720 (diff)
mtd: nand: hide in-memory BBT implementation details
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> Signed-off-by: Huang Shijie <b32955@freescale.com>
-rw-r--r--drivers/mtd/nand/nand_base.c32
-rw-r--r--drivers/mtd/nand/nand_bbt.c28
-rw-r--r--include/linux/mtd/nand.h2
3 files changed, 38 insertions, 24 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index b2ed8a8a9961..c6275a428730 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -385,22 +385,20 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
385 * block table(s) and/or marker(s)). We only allow the hardware driver to 385 * block table(s) and/or marker(s)). We only allow the hardware driver to
386 * specify how to write bad block markers to OOB (chip->block_markbad). 386 * specify how to write bad block markers to OOB (chip->block_markbad).
387 * 387 *
388 * We try operations in the following order, according to our bbt_options 388 * We try operations in the following order:
389 * (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
390 * (1) erase the affected block, to allow OOB marker to be written cleanly 389 * (1) erase the affected block, to allow OOB marker to be written cleanly
391 * (2) update in-memory BBT 390 * (2) write bad block marker to OOB area of affected block (unless flag
392 * (3) write bad block marker to OOB area of affected block 391 * NAND_BBT_NO_OOB_BBM is present)
393 * (4) update flash-based BBT 392 * (3) update the BBT
394 * Note that we retain the first error encountered in (3) or (4), finish the 393 * Note that we retain the first error encountered in (2) or (3), finish the
395 * procedures, and dump the error in the end. 394 * procedures, and dump the error in the end.
396*/ 395*/
397static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) 396static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
398{ 397{
399 struct nand_chip *chip = mtd->priv; 398 struct nand_chip *chip = mtd->priv;
400 int block, res, ret = 0; 399 int res, ret = 0;
401 int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
402 400
403 if (write_oob) { 401 if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
404 struct erase_info einfo; 402 struct erase_info einfo;
405 403
406 /* Attempt erase before marking OOB */ 404 /* Attempt erase before marking OOB */
@@ -409,24 +407,16 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
409 einfo.addr = ofs; 407 einfo.addr = ofs;
410 einfo.len = 1 << chip->phys_erase_shift; 408 einfo.len = 1 << chip->phys_erase_shift;
411 nand_erase_nand(mtd, &einfo, 0); 409 nand_erase_nand(mtd, &einfo, 0);
412 }
413
414 /* Get block number */
415 block = (int)(ofs >> chip->bbt_erase_shift);
416 /* Mark block bad in memory-based BBT */
417 if (chip->bbt)
418 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
419 410
420 /* Write bad block marker to OOB */ 411 /* Write bad block marker to OOB */
421 if (write_oob) {
422 nand_get_device(mtd, FL_WRITING); 412 nand_get_device(mtd, FL_WRITING);
423 ret = chip->block_markbad(mtd, ofs); 413 ret = chip->block_markbad(mtd, ofs);
424 nand_release_device(mtd); 414 nand_release_device(mtd);
425 } 415 }
426 416
427 /* Update flash-based bad block table */ 417 /* Mark block bad in BBT */
428 if (chip->bbt_options & NAND_BBT_USE_FLASH) { 418 if (chip->bbt) {
429 res = nand_update_bbt(mtd, ofs); 419 res = nand_markbad_bbt(mtd, ofs);
430 if (!ret) 420 if (!ret)
431 ret = res; 421 ret = res;
432 } 422 }
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index bac481a123dd..ae3fb58591cf 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -79,6 +79,8 @@
79#define BBT_ENTRY_MASK 0x03 79#define BBT_ENTRY_MASK 0x03
80#define BBT_ENTRY_SHIFT 2 80#define BBT_ENTRY_SHIFT 2
81 81
82static int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
83
82static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) 84static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
83{ 85{
84 uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT]; 86 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)
1194} 1196}
1195 1197
1196/** 1198/**
1197 * nand_update_bbt - [NAND Interface] update bad block table(s) 1199 * nand_update_bbt - update bad block table(s)
1198 * @mtd: MTD device structure 1200 * @mtd: MTD device structure
1199 * @offs: the offset of the newly marked block 1201 * @offs: the offset of the newly marked block
1200 * 1202 *
1201 * The function updates the bad block table(s). 1203 * The function updates the bad block table(s).
1202 */ 1204 */
1203int nand_update_bbt(struct mtd_info *mtd, loff_t offs) 1205static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
1204{ 1206{
1205 struct nand_chip *this = mtd->priv; 1207 struct nand_chip *this = mtd->priv;
1206 int len, res = 0; 1208 int len, res = 0;
@@ -1390,5 +1392,27 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
1390 return 1; 1392 return 1;
1391} 1393}
1392 1394
1395/**
1396 * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
1397 * @mtd: MTD device structure
1398 * @offs: offset of the bad block
1399 */
1400int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
1401{
1402 struct nand_chip *this = mtd->priv;
1403 int block, ret = 0;
1404
1405 block = (int)(offs >> this->bbt_erase_shift);
1406
1407 /* Mark bad block in memory */
1408 bbt_mark_entry(this, block, BBT_BLOCK_WORN);
1409
1410 /* Update flash-based bad block table */
1411 if (this->bbt_options & NAND_BBT_USE_FLASH)
1412 ret = nand_update_bbt(mtd, offs);
1413
1414 return ret;
1415}
1416
1393EXPORT_SYMBOL(nand_scan_bbt); 1417EXPORT_SYMBOL(nand_scan_bbt);
1394EXPORT_SYMBOL(nand_default_bbt); 1418EXPORT_SYMBOL(nand_default_bbt);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ab6363443ce8..05c5f9a0e5cc 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -625,8 +625,8 @@ extern struct nand_flash_dev nand_flash_ids[];
625extern struct nand_manufacturers nand_manuf_ids[]; 625extern struct nand_manufacturers nand_manuf_ids[];
626 626
627extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); 627extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
628extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
629extern int nand_default_bbt(struct mtd_info *mtd); 628extern int nand_default_bbt(struct mtd_info *mtd);
629extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
630extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); 630extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
631extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, 631extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
632 int allowbbt); 632 int allowbbt);