diff options
author | Brian Norris <computersforpeace@gmail.com> | 2013-07-30 20:52:59 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:06:00 -0400 |
commit | fe9ec6f282ae68ee2b634189906d6f79f480e46d (patch) | |
tree | c0ccb00f43b2f1381f1ea558bcf3f0a557273389 | |
parent | 62801eed490bb10ea7203191d1e8626c33e9f720 (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.c | 32 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 28 | ||||
-rw-r--r-- | include/linux/mtd/nand.h | 2 |
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 | */ |
397 | static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) | 396 | static 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 | ||
82 | static int nand_update_bbt(struct mtd_info *mtd, loff_t offs); | ||
83 | |||
82 | static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) | 84 | static 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 | */ |
1203 | int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | 1205 | static 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 | */ | ||
1400 | int 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 | |||
1393 | EXPORT_SYMBOL(nand_scan_bbt); | 1417 | EXPORT_SYMBOL(nand_scan_bbt); |
1394 | EXPORT_SYMBOL(nand_default_bbt); | 1418 | EXPORT_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[]; | |||
625 | extern struct nand_manufacturers nand_manuf_ids[]; | 625 | extern struct nand_manufacturers nand_manuf_ids[]; |
626 | 626 | ||
627 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); | 627 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); |
628 | extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs); | ||
629 | extern int nand_default_bbt(struct mtd_info *mtd); | 628 | extern int nand_default_bbt(struct mtd_info *mtd); |
629 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); | ||
630 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); | 630 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); |
631 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 631 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
632 | int allowbbt); | 632 | int allowbbt); |