Commit c3baf278 authored by Boris Brezillon's avatar Boris Brezillon

mtd: nand_bbt: Move BBT block selection logic out of write_bbt()

This clarifies the write_bbt() function by removing the write label
and simplifying the error/exit path.
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: default avatarKyle Roeschley <kyle.roeschley@ni.com>
parent 57d419a4
...@@ -604,6 +604,69 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf, ...@@ -604,6 +604,69 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
search_bbt(mtd, buf, md); search_bbt(mtd, buf, md);
} }
/**
* get_bbt_block - Get the first valid eraseblock suitable to store a BBT
* @this: the NAND device
* @td: the BBT description
* @md: the mirror BBT descriptor
* @chip: the CHIP selector
*
* This functions returns a positive block number pointing a valid eraseblock
* suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if
* all blocks are already used of marked bad. If td->pages[chip] was already
* pointing to a valid block we re-use it, otherwise we search for the next
* valid one.
*/
static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
struct nand_bbt_descr *md, int chip)
{
int startblock, dir, page, numblocks, i;
/*
* There was already a version of the table, reuse the page. This
* applies for absolute placement too, as we have the page number in
* td->pages.
*/
if (td->pages[chip] != -1)
return td->pages[chip] >>
(this->bbt_erase_shift - this->page_shift);
numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
if (!(td->options & NAND_BBT_PERCHIP))
numblocks *= this->numchips;
/*
* Automatic placement of the bad block table. Search direction
* top -> down?
*/
if (td->options & NAND_BBT_LASTBLOCK) {
startblock = numblocks * (chip + 1) - 1;
dir = -1;
} else {
startblock = chip * numblocks;
dir = 1;
}
for (i = 0; i < td->maxblocks; i++) {
int block = startblock + dir * i;
/* Check, if the block is bad */
switch (bbt_get_entry(this, block)) {
case BBT_BLOCK_WORN:
case BBT_BLOCK_FACTORY_BAD:
continue;
}
page = block << (this->bbt_erase_shift - this->page_shift);
/* Check, if the block is used by the mirror table */
if (!md || md->pages[chip] != page)
return block;
}
return -ENOSPC;
}
/** /**
* write_bbt - [GENERIC] (Re)write the bad block table * write_bbt - [GENERIC] (Re)write the bad block table
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -621,7 +684,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -621,7 +684,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_chip *this = mtd_to_nand(mtd); struct nand_chip *this = mtd_to_nand(mtd);
struct erase_info einfo; struct erase_info einfo;
int i, res, chip = 0; int i, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; int bits, page, offs, numblocks, sft, sftmsk;
int nrchips, pageoffs, ooboffs; int nrchips, pageoffs, ooboffs;
uint8_t msk[4]; uint8_t msk[4];
uint8_t rcode = td->reserved_block_code; uint8_t rcode = td->reserved_block_code;
...@@ -653,45 +716,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -653,45 +716,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
/* Loop through the chips */ /* Loop through the chips */
for (; chip < nrchips; chip++) { for (; chip < nrchips; chip++) {
/* int block;
* There was already a version of the table, reuse the page
* This applies for absolute placement too, as we have the block = get_bbt_block(this, td, md, chip);
* page nr. in td->pages. if (block < 0) {
*/ pr_err("No space left to write bad block table\n");
if (td->pages[chip] != -1) { res = block;
page = td->pages[chip]; goto outerr;
goto write;
} }
/* /*
* Automatic placement of the bad block table. Search direction * get_bbt_block() returns a block number, shift the value to
* top -> down? * get a page number.
*/ */
if (td->options & NAND_BBT_LASTBLOCK) { page = block << (this->bbt_erase_shift - this->page_shift);
startblock = numblocks * (chip + 1) - 1;
dir = -1;
} else {
startblock = chip * numblocks;
dir = 1;
}
for (i = 0; i < td->maxblocks; i++) {
int block = startblock + dir * i;
/* Check, if the block is bad */
switch (bbt_get_entry(this, block)) {
case BBT_BLOCK_WORN:
case BBT_BLOCK_FACTORY_BAD:
continue;
}
page = block <<
(this->bbt_erase_shift - this->page_shift);
/* Check, if the block is used by the mirror table */
if (!md || md->pages[chip] != page)
goto write;
}
pr_err("No space left to write bad block table\n");
return -ENOSPC;
write:
/* Set up shift count and masks for the flash table */ /* Set up shift count and masks for the flash table */
bits = td->options & NAND_BBT_NRBITS_MSK; bits = td->options & NAND_BBT_NRBITS_MSK;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment