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>
This commit is contained in:
Родитель
5a0edb251a
Коммит
b32843b772
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче