Commit b4d20d60 authored by Brian Norris's avatar Brian Norris Committed by David Woodhouse

mtd: nand: remove multiplied-by-2 block logic

The parent commit 771c568b ("mtd: nand: add
accessors, macros for in-memory BBT") makes the following comment obsolete:

	/*
	 * Note that numblocks is 2 * (real numblocks) here, see i+=2
	 * below as it makes shifting and masking less painful
	 */

I don't think it ever could have been "less painful" to have to shift an
extra bit (or 2, or 3) at various points in nand_bbt.c (and even
outside, since we leak our in-memory format). But now it is certainly
more painful, since we have nice macros and functions to retrieve the
relevant portions of the BBT.

This patch removes any points where the block number is
doubled/halved/otherwise-shifted, instead representing the block number
in its most natural form: as the actual block number.
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 771c568b
...@@ -181,7 +181,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td) ...@@ -181,7 +181,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
* @page: the starting page * @page: the starting page
* @num: the number of bbt descriptors to read * @num: the number of bbt descriptors to read
* @td: the bbt describtion table * @td: the bbt describtion table
* @offs: offset in the memory table * @offs: block number offset in the table
* *
* Read the bad block table starting from page. * Read the bad block table starting from page.
*/ */
...@@ -231,15 +231,15 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, ...@@ -231,15 +231,15 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
/* Analyse data */ /* Analyse data */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
uint8_t dat = buf[i]; uint8_t dat = buf[i];
for (j = 0; j < 8; j += bits, act += 2) { for (j = 0; j < 8; j += bits, act++) {
uint8_t tmp = (dat >> j) & msk; uint8_t tmp = (dat >> j) & msk;
if (tmp == msk) if (tmp == msk)
continue; continue;
if (reserved_block_code && (tmp == reserved_block_code)) { if (reserved_block_code && (tmp == reserved_block_code)) {
pr_info("nand_read_bbt: reserved block at 0x%012llx\n", pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); (loff_t)(offs + act) <<
bbt_mark_entry(this, (offs << 2) + this->bbt_erase_shift);
(act >> 1), bbt_mark_entry(this, offs + act,
BBT_BLOCK_RESERVED); BBT_BLOCK_RESERVED);
mtd->ecc_stats.bbtblocks++; mtd->ecc_stats.bbtblocks++;
continue; continue;
...@@ -249,15 +249,14 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, ...@@ -249,15 +249,14 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
* move this message to pr_debug. * move this message to pr_debug.
*/ */
pr_info("nand_read_bbt: bad block at 0x%012llx\n", pr_info("nand_read_bbt: bad block at 0x%012llx\n",
(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); (loff_t)(offs + act) <<
this->bbt_erase_shift);
/* Factory marked bad or worn out? */ /* Factory marked bad or worn out? */
if (tmp == 0) if (tmp == 0)
bbt_mark_entry(this, (offs << 2) + bbt_mark_entry(this, offs + act,
(act >> 1),
BBT_BLOCK_FACTORY_BAD); BBT_BLOCK_FACTORY_BAD);
else else
bbt_mark_entry(this, (offs << 2) + bbt_mark_entry(this, offs + act,
(act >> 1),
BBT_BLOCK_WORN); BBT_BLOCK_WORN);
mtd->ecc_stats.badblocks++; mtd->ecc_stats.badblocks++;
} }
...@@ -293,7 +292,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc ...@@ -293,7 +292,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
td, offs); td, offs);
if (res) if (res)
return res; return res;
offs += this->chipsize >> (this->bbt_erase_shift + 2); offs += this->chipsize >> this->bbt_erase_shift;
} }
} else { } else {
res = read_bbt(mtd, buf, td->pages[0], res = read_bbt(mtd, buf, td->pages[0],
...@@ -517,11 +516,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -517,11 +516,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
} }
if (chip == -1) { if (chip == -1) {
/* numblocks = mtd->size >> this->bbt_erase_shift;
* Note that numblocks is 2 * (real numblocks) here, see i+=2
* below as it makes shifting and masking less painful
*/
numblocks = mtd->size >> (this->bbt_erase_shift - 1);
startblock = 0; startblock = 0;
from = 0; from = 0;
} else { } else {
...@@ -530,16 +525,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -530,16 +525,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
chip + 1, this->numchips); chip + 1, this->numchips);
return -EINVAL; return -EINVAL;
} }
numblocks = this->chipsize >> (this->bbt_erase_shift - 1); numblocks = this->chipsize >> this->bbt_erase_shift;
startblock = chip * numblocks; startblock = chip * numblocks;
numblocks += startblock; numblocks += startblock;
from = (loff_t)startblock << (this->bbt_erase_shift - 1); from = (loff_t)startblock << this->bbt_erase_shift;
} }
if (this->bbt_options & NAND_BBT_SCANLASTPAGE) if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
from += mtd->erasesize - (mtd->writesize * numpages); from += mtd->erasesize - (mtd->writesize * numpages);
for (i = startblock; i < numblocks;) { for (i = startblock; i < numblocks; i++) {
int ret; int ret;
BUG_ON(bd->options & NAND_BBT_NO_OOB); BUG_ON(bd->options & NAND_BBT_NO_OOB);
...@@ -554,13 +549,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -554,13 +549,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
return ret; return ret;
if (ret) { if (ret) {
bbt_mark_entry(this, i >> 1, BBT_BLOCK_FACTORY_BAD); bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD);
pr_warn("Bad eraseblock %d at 0x%012llx\n", pr_warn("Bad eraseblock %d at 0x%012llx\n",
i >> 1, (unsigned long long)from); i, (unsigned long long)from);
mtd->ecc_stats.badblocks++; mtd->ecc_stats.badblocks++;
} }
i += 2;
from += (1 << this->bbt_erase_shift); from += (1 << this->bbt_erase_shift);
} }
return 0; return 0;
...@@ -683,9 +677,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -683,9 +677,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
struct erase_info einfo; struct erase_info einfo;
int i, j, res, chip = 0; int i, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
int nrchips, bbtoffs, 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;
size_t retlen, len = 0; size_t retlen, len = 0;
...@@ -775,8 +769,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -775,8 +769,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
default: return -EINVAL; default: return -EINVAL;
} }
bbtoffs = chip * (numblocks >> 2);
to = ((loff_t)page) << this->page_shift; to = ((loff_t)page) << this->page_shift;
/* Must we save the block contents? */ /* Must we save the block contents? */
...@@ -841,16 +833,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ...@@ -841,16 +833,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
buf[ooboffs + td->veroffs] = td->version[chip]; buf[ooboffs + td->veroffs] = td->version[chip];
/* Walk through the memory table */ /* Walk through the memory table */
for (i = 0; i < numblocks;) { for (i = 0; i < numblocks; i++) {
uint8_t dat; uint8_t dat;
dat = bbt_get_entry(this, (bbtoffs << 2) + i); int sftcnt = (i << (3 - sft)) & sftmsk;
for (j = 0; j < 4; j++, i++) { dat = bbt_get_entry(this, chip * numblocks + i);
int sftcnt = (i << (3 - sft)) & sftmsk; /* Do not store the reserved bbt blocks! */
/* Do not store the reserved bbt blocks! */ buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
buf[offs + (i >> sft)] &=
~(msk[dat & 0x03] << sftcnt);
dat >>= 2;
}
} }
memset(&einfo, 0, sizeof(einfo)); memset(&einfo, 0, sizeof(einfo));
...@@ -1053,12 +1041,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) ...@@ -1053,12 +1041,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
if (td->pages[i] == -1) if (td->pages[i] == -1)
continue; continue;
block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
block <<= 1; oldval = bbt_get_entry(this, block);
oldval = bbt_get_entry(this, block >> 1); bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED);
if ((oldval != BBT_BLOCK_RESERVED) && if ((oldval != BBT_BLOCK_RESERVED) &&
td->reserved_block_code) td->reserved_block_code)
nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1)); nand_update_bbt(mtd, (loff_t)block <<
this->bbt_erase_shift);
continue; continue;
} }
update = 0; update = 0;
...@@ -1066,13 +1054,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) ...@@ -1066,13 +1054,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
block = ((i + 1) * nrblocks) - td->maxblocks; block = ((i + 1) * nrblocks) - td->maxblocks;
else else
block = i * nrblocks; block = i * nrblocks;
block <<= 1;
for (j = 0; j < td->maxblocks; j++) { for (j = 0; j < td->maxblocks; j++) {
oldval = bbt_get_entry(this, block >> 1); oldval = bbt_get_entry(this, block);
bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED); bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
if (oldval != BBT_BLOCK_RESERVED) if (oldval != BBT_BLOCK_RESERVED)
update = 1; update = 1;
block += 2; block++;
} }
/* /*
* If we want reserved blocks to be recorded to flash, and some * If we want reserved blocks to be recorded to flash, and some
...@@ -1080,7 +1067,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) ...@@ -1080,7 +1067,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
* bbts. This should only happen once. * bbts. This should only happen once.
*/ */
if (update && td->reserved_block_code) if (update && td->reserved_block_code)
nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); nand_update_bbt(mtd, (loff_t)(block - 1) <<
this->bbt_erase_shift);
} }
} }
...@@ -1385,13 +1373,12 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) ...@@ -1385,13 +1373,12 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
int block; int block;
uint8_t res; uint8_t res;
/* Get block number * 2 */ block = (int)(offs >> this->bbt_erase_shift);
block = (int)(offs >> (this->bbt_erase_shift - 1)); res = bbt_get_entry(this, block);
res = bbt_get_entry(this, block >> 1);
pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: " pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: "
"(block %d) 0x%02x\n", "(block %d) 0x%02x\n",
(unsigned int)offs, block >> 1, res); (unsigned int)offs, block, res);
switch ((int)res) { switch ((int)res) {
case BBT_BLOCK_GOOD: case BBT_BLOCK_GOOD:
......
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