aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2013-07-30 20:52:59 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2013-08-30 11:48:17 -0400
commitb32843b772db6024336e36c39359d8edc3b416ab (patch)
tree9e4cd381d3abfa5075dceb1ff544908645431a4b /drivers/mtd
parent5a0edb251ae91c6f9b1f28dc165becd955666118 (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.c32
-rw-r--r--drivers/mtd/nand/nand_bbt.c28
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*/
386static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) 385static 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
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);