summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorStefan Riedmueller <s.riedmueller@phytec.de>2021-06-25 14:38:21 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2021-07-16 01:06:22 +0200
commit1a57b13e6017d2af575f4f42e848aa0b64d4bcf1 (patch)
treec37acdf5000773a5792412166f83abb10e35a117 /drivers/mtd
parent778cb8e39f6ec252be50fc3850d66f3dcbd5dd5a (diff)
downloadlinux-1a57b13e6017d2af575f4f42e848aa0b64d4bcf1.tar.bz2
mtd: rawnand: nand_bbt: Skip bad blocks when searching for the BBT in NAND
The blocks containing the bad block table can become bad as well. So make sure to skip any blocks that are marked bad when searching for the bad block table. Otherwise in very rare cases where two BBT blocks wear out it might happen that an obsolete BBT is used instead of a newer available version. This only applies to drivers which make use of a bad block marker in flash. Other drivers won't be able to identify bad BBT blocks and thus can't skip these. Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20210625123821.207458-1-s.riedmueller@phytec.de
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index dced32a126d9..b7ad030225f8 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -447,6 +447,35 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
return 0;
}
+/* Check if a potential BBT block is marked as bad */
+static int bbt_block_checkbad(struct nand_chip *this, struct nand_bbt_descr *td,
+ loff_t offs, uint8_t *buf)
+{
+ struct nand_bbt_descr *bd = this->badblock_pattern;
+
+ /*
+ * No need to check for a bad BBT block if the BBM area overlaps with
+ * the bad block table marker area in OOB since writing a BBM here
+ * invalidates the bad block table marker anyway.
+ */
+ if (!(td->options & NAND_BBT_NO_OOB) &&
+ td->offs >= bd->offs && td->offs < bd->offs + bd->len)
+ return 0;
+
+ /*
+ * There is no point in checking for a bad block marker if writing
+ * such marker is not supported
+ */
+ if (this->bbt_options & NAND_BBT_NO_OOB_BBM ||
+ this->options & NAND_NO_BBM_QUIRK)
+ return 0;
+
+ if (scan_block_fast(this, bd, offs, buf) > 0)
+ return 1;
+
+ return 0;
+}
+
/**
* create_bbt - [GENERIC] Create a bad block table by scanning the device
* @this: NAND chip object
@@ -560,6 +589,10 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf,
int actblock = startblock + dir * block;
loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
+ /* Check if block is marked bad */
+ if (bbt_block_checkbad(this, td, offs, buf))
+ continue;
+
/* Read first page */
scan_read(this, buf, offs, mtd->writesize, td);
if (!check_pattern(buf, scanlen, mtd->writesize, td)) {