diff options
author | Brian Norris <computersforpeace@gmail.com> | 2013-07-30 20:52:59 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2013-08-30 11:48:17 -0400 |
commit | b32843b772db6024336e36c39359d8edc3b416ab (patch) | |
tree | 9e4cd381d3abfa5075dceb1ff544908645431a4b /drivers/mtd | |
parent | 5a0edb251ae91c6f9b1f28dc165becd955666118 (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>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 32 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 28 |
2 files changed, 37 insertions, 23 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5a7467c33757..9a487580e370 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -374,22 +374,20 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
374 | * block table(s) and/or marker(s)). We only allow the hardware driver to | 374 | * block table(s) and/or marker(s)). We only allow the hardware driver to |
375 | * specify how to write bad block markers to OOB (chip->block_markbad). | 375 | * specify how to write bad block markers to OOB (chip->block_markbad). |
376 | * | 376 | * |
377 | * We try operations in the following order, according to our bbt_options | 377 | * We try operations in the following order: |
378 | * (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): | ||
379 | * (1) erase the affected block, to allow OOB marker to be written cleanly | 378 | * (1) erase the affected block, to allow OOB marker to be written cleanly |
380 | * (2) update in-memory BBT | 379 | * (2) write bad block marker to OOB area of affected block (unless flag |
381 | * (3) write bad block marker to OOB area of affected block | 380 | * NAND_BBT_NO_OOB_BBM is present) |
382 | * (4) update flash-based BBT | 381 | * (3) update the BBT |
383 | * Note that we retain the first error encountered in (3) or (4), finish the | 382 | * Note that we retain the first error encountered in (2) or (3), finish the |
384 | * procedures, and dump the error in the end. | 383 | * procedures, and dump the error in the end. |
385 | */ | 384 | */ |
386 | static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) | 385 | static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) |
387 | { | 386 | { |
388 | struct nand_chip *chip = mtd->priv; | 387 | struct nand_chip *chip = mtd->priv; |
389 | int block, res, ret = 0; | 388 | int res, ret = 0; |
390 | int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); | ||
391 | 389 | ||
392 | if (write_oob) { | 390 | if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { |
393 | struct erase_info einfo; | 391 | struct erase_info einfo; |
394 | 392 | ||
395 | /* Attempt erase before marking OOB */ | 393 | /* Attempt erase before marking OOB */ |
@@ -398,24 +396,16 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) | |||
398 | einfo.addr = ofs; | 396 | einfo.addr = ofs; |
399 | einfo.len = 1 << chip->phys_erase_shift; | 397 | einfo.len = 1 << chip->phys_erase_shift; |
400 | nand_erase_nand(mtd, &einfo, 0); | 398 | nand_erase_nand(mtd, &einfo, 0); |
401 | } | ||
402 | |||
403 | /* Get block number */ | ||
404 | block = (int)(ofs >> chip->bbt_erase_shift); | ||
405 | /* Mark block bad in memory-based BBT */ | ||
406 | if (chip->bbt) | ||
407 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
408 | 399 | ||
409 | /* Write bad block marker to OOB */ | 400 | /* Write bad block marker to OOB */ |
410 | if (write_oob) { | ||
411 | nand_get_device(mtd, FL_WRITING); | 401 | nand_get_device(mtd, FL_WRITING); |
412 | ret = chip->block_markbad(mtd, ofs); | 402 | ret = chip->block_markbad(mtd, ofs); |
413 | nand_release_device(mtd); | 403 | nand_release_device(mtd); |
414 | } | 404 | } |
415 | 405 | ||
416 | /* Update flash-based bad block table */ | 406 | /* Mark block bad in BBT */ |
417 | if (chip->bbt_options & NAND_BBT_USE_FLASH) { | 407 | if (chip->bbt) { |
418 | res = nand_update_bbt(mtd, ofs); | 408 | res = nand_markbad_bbt(mtd, ofs); |
419 | if (!ret) | 409 | if (!ret) |
420 | ret = res; | 410 | ret = res; |
421 | } | 411 | } |
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); |