mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/16] NAND update (1st step)
@ 2018-10-28 21:19 Ladislav Michl
  2018-10-28 21:21 ` [PATCH 01/16] mtd: nand: refactor chip->block_markbad interface Ladislav Michl
                   ` (15 more replies)
  0 siblings, 16 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:19 UTC (permalink / raw)
  To: barebox

The ultimate goal we are still quite far away is to update MTD subsystem
to something more recent. As it is rather hard to accomplish by simply
importing core files from linux-4.19 as there are many NAND drivers
not even present in mainline kernel in current (barebox) form, let's
choose incremental updating.

This patchset is rather selfish (and I'm sorry for that); its sole
purpose is being able to use Toshiba NAND (needing 8bit ECC) on
AT91SAM9G20 based board. This is also the only board I was able to
do runtime testing. To do this "mtd: atmel_nand: Add per board ECC
setup" patch is introduced. This shall be considered temporary
solution. As MTD core will be updated, we can import rewritten
Atmel NAND driver.

There more in queue, most notably mtd_ooblayout_ops conversion,
but let's focus on this serie first :)

Special thanks goes to Boris Brezillon for guiding me though pitfalls
of NAND devices while debugging Toshiba NAND support in Barebox.

Comments (or even help with fixes) very welcome, this will be likely
a bit painfull update.

Ladislav Michl (16):
  mtd: nand: refactor chip->block_markbad interface
  mtd: nand: remove multiplied-by-2 block logic
  mtd: nand: hide in-memory BBT implementation details
  mtd: nand: remove NAND_BBT_SCANEMPTY
  mtd: nand: Request strength instead of bytes for soft BCH
  mtd: atmel_nand: Add per board ECC setup
  mtd: nand: simplify nand_bch_init() usage
  mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES
  mtd: nand_bbt: handle error case for nand_create_badblock_pattern()
  mtd: nand_bbt: make nand_scan_bbt() static
  mtd: nand_bbt: unify/fix error handling in nand_scan_bbt()
  mtd: nand_bbt: Move BBT block selection logic out of write_bbt()
  mtd: nand_bbt: scan for next free bbt block if writing bbt fails
  mtd: nand: Kill the chip->scan_bbt() hook
  mtd: nand: Kill cellinfo
  mtd: nand: detect OOB size for Toshiba 24nm raw SLC

 arch/arm/mach-at91/include/mach/board.h |   2 +
 drivers/mtd/nand/atmel_nand.c           |   3 +
 drivers/mtd/nand/nand_base.c            | 274 +++++++++--------
 drivers/mtd/nand/nand_bbt.c             | 385 ++++++++++++++----------
 drivers/mtd/nand/nand_bch.c             |  27 +-
 drivers/mtd/nand/nand_imx_bbm.c         |   2 +-
 drivers/mtd/nand/nand_mxs.c             |  27 +-
 drivers/mtd/nand/nand_omap_gpmc.c       |   1 -
 include/linux/mtd/bbm.h                 |   4 -
 include/linux/mtd/nand.h                |  13 +-
 include/linux/mtd/nand_bch.h            |   8 +-
 11 files changed, 415 insertions(+), 331 deletions(-)

-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/16] mtd: nand: refactor chip->block_markbad interface
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
@ 2018-10-28 21:21 ` Ladislav Michl
  2018-10-28 21:21 ` [PATCH 02/16] mtd: nand: remove multiplied-by-2 block logic Ladislav Michl
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:21 UTC (permalink / raw)
  To: barebox

Linux commit 5a0edb251ae9 adapted for Barebox:

  The chip->block_markbad pointer should really only be responsible for
  writing a bad block marker for new bad blocks. It should not take care
  of BBT-related functionality, nor should it handle bookkeeping of bad
  block stats.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c | 87 +++++++++++++++++++++---------------
 1 file changed, 52 insertions(+), 35 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ccf961504..2025d176e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -326,13 +326,58 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 }
 
 /**
- * nand_default_block_markbad - [DEFAULT] mark a block bad
+ * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
  * @mtd: MTD device structure
  * @ofs: offset from device start
  *
  * This is the default implementation, which can be overridden by a hardware
- * specific driver. We try operations in the following order, according to our
- * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
+ * specific driver. It provides the details for writing a bad block marker to a
+ * block.
+ */
+static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops ops;
+	uint8_t buf[2] = { 0, 0 };
+	int ret = 0, res, i = 0;
+
+	ops.datbuf = NULL;
+	ops.oobbuf = buf;
+	ops.ooboffs = chip->badblockpos;
+	if (chip->options & NAND_BUSWIDTH_16) {
+		ops.ooboffs &= ~0x01;
+		ops.len = ops.ooblen = 2;
+	} else {
+		ops.len = ops.ooblen = 1;
+	}
+	ops.mode = MTD_OPS_PLACE_OOB;
+
+	/* Write to first/last page(s) if necessary */
+	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+		ofs += mtd->erasesize - mtd->writesize;
+	do {
+		res = nand_do_write_oob(mtd, ofs, &ops);
+		if (!ret)
+			ret = res;
+
+		i++;
+		ofs += mtd->writesize;
+	} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+
+	return ret;
+}
+
+/**
+ * nand_block_markbad_lowlevel - mark a block bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ *
+ * This function performs the generic NAND bad block marking steps (i.e., bad
+ * 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):
  *  (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
@@ -340,11 +385,10 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
  * Note that we retain the first error encountered in (3) or (4), finish the
  * procedures, and dump the error in the end.
 */
-static __maybe_unused  int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
 	struct nand_chip *chip = mtd->priv;
-	uint8_t buf[2] = { 0, 0 };
-	int block, res, ret = 0, i = 0;
+	int block, res, ret = 0;
 	int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
 
 	if (write_oob) {
@@ -366,34 +410,8 @@ static __maybe_unused  int nand_default_block_markbad(struct mtd_info *mtd, loff
 
 	/* Write bad block marker to OOB */
 	if (write_oob) {
-		struct mtd_oob_ops ops;
-		loff_t wr_ofs = ofs;
-
 		nand_get_device(mtd, FL_WRITING);
-
-		ops.datbuf = NULL;
-		ops.oobbuf = buf;
-		ops.ooboffs = chip->badblockpos;
-		if (chip->options & NAND_BUSWIDTH_16) {
-			ops.ooboffs &= ~0x01;
-			ops.len = ops.ooblen = 2;
-		} else {
-			ops.len = ops.ooblen = 1;
-		}
-		ops.mode = MTD_OPS_PLACE_OOB;
-
-		/* Write to first/last page(s) if necessary */
-		if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
-			wr_ofs += mtd->erasesize - mtd->writesize;
-		do {
-			res = nand_do_write_oob(mtd, wr_ofs, &ops);
-			if (!ret)
-				ret = res;
-
-			i++;
-			wr_ofs += mtd->writesize;
-		} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
-
+		ret = chip->block_markbad(mtd, ofs);
 		nand_release_device(mtd);
 	}
 
@@ -2786,7 +2804,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
  */
 static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
 	int ret;
 
 	if (!IS_ENABLED(CONFIG_MTD_WRITE))
@@ -2800,7 +2817,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		return ret;
 	}
 
-	return chip->block_markbad(mtd, ofs);
+	return nand_block_markbad_lowlevel(mtd, ofs);
 }
 
 /**
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 02/16] mtd: nand: remove multiplied-by-2 block logic
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
  2018-10-28 21:21 ` [PATCH 01/16] mtd: nand: refactor chip->block_markbad interface Ladislav Michl
@ 2018-10-28 21:21 ` Ladislav Michl
  2018-10-28 21:22 ` [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details Ladislav Michl
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:21 UTC (permalink / raw)
  To: barebox

Linux commit b4d20d601f1e adapted for Barebox

  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: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 83 ++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 48 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 94a2e5783..4a0ee1db6 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -179,7 +179,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
  * @page: the starting page
  * @num: the number of bbt descriptors to read
  * @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.
  */
@@ -229,29 +229,28 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		/* Analyse data */
 		for (i = 0; i < len; 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;
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
 					pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
-						 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
-					bbt_mark_entry(this, (offs << 2) +
-							(act >> 1),
+						 (loff_t)(offs + act) <<
+						 this->bbt_erase_shift);
+					bbt_mark_entry(this, offs + act,
 							BBT_BLOCK_RESERVED);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
 				pr_debug("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? */
 				if (tmp == 0)
-					bbt_mark_entry(this, (offs << 2) +
-							(act >> 1),
+					bbt_mark_entry(this, offs + act,
 							BBT_BLOCK_FACTORY_BAD);
 				else
-					bbt_mark_entry(this, (offs << 2) +
-							(act >> 1),
+					bbt_mark_entry(this, offs + act,
 							BBT_BLOCK_WORN);
 				mtd->ecc_stats.badblocks++;
 			}
@@ -287,7 +286,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 					td, offs);
 			if (res)
 				return res;
-			offs += this->chipsize >> (this->bbt_erase_shift + 2);
+			offs += this->chipsize >> this->bbt_erase_shift;
 		}
 	} else {
 		res = read_bbt(mtd, buf, td->pages[0],
@@ -511,11 +510,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	}
 
 	if (chip == -1) {
-		/*
-		 * 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);
+		numblocks = mtd->size >> this->bbt_erase_shift;
 		startblock = 0;
 		from = 0;
 	} else {
@@ -524,16 +519,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
-		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
+		numblocks = this->chipsize >> this->bbt_erase_shift;
 		startblock = chip * numblocks;
 		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)
 		from += mtd->erasesize - (mtd->writesize * numpages);
 
-	for (i = startblock; i < numblocks;) {
+	for (i = startblock; i < numblocks; i++) {
 		int ret;
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
@@ -548,13 +543,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 			return 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",
-				i >> 1, (unsigned long long)from);
+				i, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
 
-		i += 2;
 		from += (1 << this->bbt_erase_shift);
 	}
 	return 0;
@@ -674,9 +668,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 {
 	struct nand_chip *this = mtd->priv;
 	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 nrchips, bbtoffs, pageoffs, ooboffs;
+	int nrchips, pageoffs, ooboffs;
 	uint8_t msk[4];
 	uint8_t rcode = td->reserved_block_code;
 	size_t retlen, len = 0;
@@ -766,8 +760,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		default: return -EINVAL;
 		}
 
-		bbtoffs = chip * (numblocks >> 2);
-
 		to = ((loff_t)page) << this->page_shift;
 
 		/* Must we save the block contents? */
@@ -830,16 +822,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			buf[ooboffs + td->veroffs] = td->version[chip];
 
 		/* Walk through the memory table */
-		for (i = 0; i < numblocks;) {
+		for (i = 0; i < numblocks; i++) {
 			uint8_t dat;
-			dat = bbt_get_entry(this, (bbtoffs << 2) + i);
-			for (j = 0; j < 4; j++, i++) {
-				int sftcnt = (i << (3 - sft)) & sftmsk;
-				/* Do not store the reserved bbt blocks! */
-				buf[offs + (i >> sft)] &=
-					~(msk[dat & 0x03] << sftcnt);
-				dat >>= 2;
-			}
+			int sftcnt = (i << (3 - sft)) & sftmsk;
+			dat = bbt_get_entry(this, chip * numblocks + i);
+			/* Do not store the reserved bbt blocks! */
+			buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
 		}
 
 		memset(&einfo, 0, sizeof(einfo));
@@ -1042,12 +1030,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 			if (td->pages[i] == -1)
 				continue;
 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
-			block <<= 1;
-			oldval = bbt_get_entry(this, block >> 1);
-			bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED);
+			oldval = bbt_get_entry(this, block);
+			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
 			if ((oldval != BBT_BLOCK_RESERVED) &&
 					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;
 		}
 		update = 0;
@@ -1055,13 +1043,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 			block = ((i + 1) * nrblocks) - td->maxblocks;
 		else
 			block = i * nrblocks;
-		block <<= 1;
 		for (j = 0; j < td->maxblocks; j++) {
-			oldval = bbt_get_entry(this, block >> 1);
-			bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED);
+			oldval = bbt_get_entry(this, block);
+			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
 			if (oldval != BBT_BLOCK_RESERVED)
 				update = 1;
-			block += 2;
+			block++;
 		}
 		/*
 		 * If we want reserved blocks to be recorded to flash, and some
@@ -1069,7 +1056,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 		 * bbts.  This should only happen once.
 		 */
 		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);
 	}
 }
 
@@ -1374,12 +1362,11 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	int block;
 	uint8_t res;
 
-	/* Get block number * 2 */
-	block = (int)(offs >> (this->bbt_erase_shift - 1));
-	res = bbt_get_entry(this, block >> 1);
+	block = (int)(offs >> this->bbt_erase_shift);
+	res = bbt_get_entry(this, block);
 
 	pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-		 (unsigned int)offs, block >> 1, res);
+		 (unsigned int)offs, block, res);
 
 	switch ((int)res) {
 	case BBT_BLOCK_GOOD:
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
  2018-10-28 21:21 ` [PATCH 01/16] mtd: nand: refactor chip->block_markbad interface Ladislav Michl
  2018-10-28 21:21 ` [PATCH 02/16] mtd: nand: remove multiplied-by-2 block logic Ladislav Michl
@ 2018-10-28 21:22 ` Ladislav Michl
  2018-10-29 10:07   ` Ladislav Michl
  2018-10-28 21:22 ` [PATCH 04/16] mtd: nand: remove NAND_BBT_SCANEMPTY Ladislav Michl
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:22 UTC (permalink / raw)
  To: barebox

Linux commit b32843b772db adapted for Barebox:

  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: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c | 125 ++++++++++++++++++-----------------
 drivers/mtd/nand/nand_bbt.c  |  39 ++++++++++-
 include/linux/mtd/nand.h     |   4 +-
 3 files changed, 104 insertions(+), 64 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 2025d176e..d4b7167f5 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -36,13 +36,13 @@
 #include <clock.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
-#include <linux/err.h>
+#include <linux/mtd/nand_bch.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/err.h>
 #include <asm/byteorder.h>
 #include <io.h>
 #include <malloc.h>
 #include <module.h>
-#include <linux/mtd/nand_bch.h>
 
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_ecclayout nand_oob_8 = {
@@ -376,22 +376,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 */
@@ -400,24 +398,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 (IS_ENABLED(CONFIG_NAND_BBT) && 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;
 	}
@@ -428,6 +418,54 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 	return ret;
 }
 
+/**
+ * nand_block_markgood_lowlevel - mark a block good
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ *
+ * We try operations in the following order:
+ *  (1) erase the affected block
+ *  (2) check bad block marker
+ *  (3) update the BBT
+ */
+static int nand_block_markgood_lowlevel(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	bool allow_erasebad;
+	int ret;
+
+	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
+		struct erase_info einfo;
+
+		/* Attempt erase possibly bad block */
+		allow_erasebad = mtd->allow_erasebad;
+		mtd->allow_erasebad = true;
+		memset(&einfo, 0, sizeof(einfo));
+		einfo.mtd = mtd;
+		einfo.addr = ofs;
+		einfo.len = 1 << chip->phys_erase_shift;
+		nand_erase_nand(mtd, &einfo, 0);
+		mtd->allow_erasebad = allow_erasebad;
+
+		/* Still bad? */
+		ret = chip->block_bad(mtd, ofs, 0);
+		if (ret)
+			return ret;
+	}
+
+	/* Mark block good in BBT */
+	if (chip->bbt) {
+		ret = nand_markgood_bbt(mtd, ofs);
+		if (ret)
+			return ret;
+	}
+
+	if (mtd->ecc_stats.badblocks > 0)
+		mtd->ecc_stats.badblocks--;
+
+	return 0;
+}
+
 /**
  * nand_check_wp - [GENERIC] check if the chip is write protected
  * @mtd: MTD device structure
@@ -471,38 +509,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
 	return chip->block_bad(mtd, ofs, getchip);
 }
 
-/**
- * nand_default_block_markgood - [DEFAULT] mark a block good
- * @mtd:	MTD device structure
- * @ofs:	offset from device start
- *
- * This is the default implementation, which can be overridden by
- * a hardware specific driver.
-*/
-static __maybe_unused  int nand_default_block_markgood(struct mtd_info *mtd, loff_t ofs)
-{
-	struct nand_chip *chip = mtd->priv;
-	int block, res, ret = 0;
-
-	/* Get block number */
-	block = (int)(ofs >> chip->bbt_erase_shift);
-	/* Mark block good in memory-based BBT */
-	if (chip->bbt)
-		chip->bbt[block >> 2] &= ~(0x01 << ((block & 0x03) << 1));
-
-	/* Update flash-based bad block table */
-	if (IS_ENABLED(CONFIG_NAND_BBT) && chip->bbt_options & NAND_BBT_USE_FLASH) {
-		res = nand_update_bbt(mtd, ofs);
-		if (!ret)
-			ret = res;
-	}
-
-	if (!ret)
-		mtd->ecc_stats.badblocks++;
-
-	return ret;
-}
-
 /* Wait for the ready pin, after a command. The timeout is caught later. */
 void nand_wait_ready(struct mtd_info *mtd)
 {
@@ -2821,13 +2827,12 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 }
 
 /**
- * nand_block_markgood - [MTD Interface] Mark block at the given offset as bad
+ * nand_block_markgood - [MTD Interface] Mark block at the given offset as good
  * @mtd: MTD device structure
  * @ofs: offset relative to mtd start
  */
 static int nand_block_markgood(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
 	int ret;
 
 	if (!IS_ENABLED(CONFIG_MTD_WRITE))
@@ -2841,7 +2846,7 @@ static int nand_block_markgood(struct mtd_info *mtd, loff_t ofs)
 	if (!ret)
 		return 0;
 
-	return chip->block_markgood(mtd, ofs);
+	return nand_block_markgood_lowlevel(mtd, ofs);
 }
 
 /**
@@ -2925,8 +2930,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 #ifdef CONFIG_MTD_WRITE
 	if (!chip->block_markbad)
 		chip->block_markbad = nand_default_block_markbad;
-	if (!chip->block_markgood)
-		chip->block_markgood = nand_default_block_markgood;
 	if (!chip->write_buf)
 		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
 #endif
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 4a0ee1db6..b54936a43 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1183,7 +1183,7 @@ 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
  *
@@ -1379,6 +1379,43 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	return 1;
 }
 
+static int nand_mark_bbt(struct mtd_info *mtd, loff_t offs, uint8_t mark)
+{
+	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, mark);
+
+	/* Update flash-based bad block table */
+	if (this->bbt_options & NAND_BBT_USE_FLASH)
+		ret = nand_update_bbt(mtd, offs);
+
+	return ret;
+}
+
+/**
+ * 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)
+{
+	return nand_mark_bbt(mtd, offs, BBT_BLOCK_WORN);
+}
+
+/**
+ * nand_markbad_bbt - [NAND Interface] Mark a block good in the BBT
+ * @mtd: MTD device structure
+ * @offs: offset of the good block
+ */
+int nand_markgood_bbt(struct mtd_info *mtd, loff_t offs)
+{
+	return nand_mark_bbt(mtd, offs, BBT_BLOCK_GOOD);
+}
+
 EXPORT_SYMBOL(nand_scan_bbt);
 EXPORT_SYMBOL(nand_default_bbt);
 EXPORT_SYMBOL_GPL(nand_update_bbt);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ec2237f7c..8caf5edec 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -398,7 +398,6 @@ struct nand_buffers {
  * @select_chip:	[REPLACEABLE] select chip nr
  * @block_bad:		[REPLACEABLE] check, if the block is bad
  * @block_markbad:	[REPLACEABLE] mark the block bad
- * @block_markgood:	[REPLACEABLE] mark the block good
  * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific function for controlling
  *			ALE/CLE/nCE. Also used to write command and address
  * @init_size:		[BOARDSPECIFIC] hardwarespecific function for setting
@@ -484,7 +483,6 @@ struct nand_chip {
 	void (*select_chip)(struct mtd_info *mtd, int chip);
 	int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-	int (*block_markgood)(struct mtd_info *mtd, loff_t ofs);
 	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
 	int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
 			u8 *id_data);
@@ -639,6 +637,8 @@ 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_markgood_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);
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 04/16] mtd: nand: remove NAND_BBT_SCANEMPTY
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (2 preceding siblings ...)
  2018-10-28 21:22 ` [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details Ladislav Michl
@ 2018-10-28 21:22 ` Ladislav Michl
  2018-10-28 21:22 ` [PATCH 05/16] mtd: nand: Request strength instead of bytes for soft BCH Ladislav Michl
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:22 UTC (permalink / raw)
  To: barebox

Relevant part of Linux commit dad2256269cb:

  NAND_BBT_SCANEMPTY is a strange, badly-supported option with omap as its
  single remaining user.

  NAND_BBT_SCANEMPTY was likely used by accident in omap2[1]. And anyway,
  omap2 doesn't scan the chip for bad blocks (courtesy of
  NAND_SKIP_BBTSCAN), and so its use of this option is irrelevant.

  This patch drops the NAND_BBT_SCANEMPTY option.

  [1] http://lists.infradead.org/pipermail/linux-mtd/2012-July/042902.html

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c       | 33 +++++--------------------------
 drivers/mtd/nand/nand_omap_gpmc.c |  2 +-
 include/linux/mtd/bbm.h           |  2 --
 3 files changed, 6 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b54936a43..19888589f 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -106,33 +106,17 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
  * @td: search pattern descriptor
  *
  * Check for a pattern at the given place. Used to search bad block tables and
- * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
- * all bytes except the pattern area contain 0xff.
+ * good / bad block identifiers.
  */
 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
-	int end = 0;
-	uint8_t *p = buf;
-
 	if (td->options & NAND_BBT_NO_OOB)
 		return check_pattern_no_oob(buf, td);
 
-	end = paglen + td->offs;
-	if (td->options & NAND_BBT_SCANEMPTY)
-		if (memchr_inv(p, 0xff, end))
-			return -1;
-	p += end;
-
 	/* Compare the pattern */
-	if (memcmp(p, td->pattern, td->len))
+	if (memcmp(buf + paglen + td->offs, td->pattern, td->len))
 		return -1;
 
-	if (td->options & NAND_BBT_SCANEMPTY) {
-		p += td->len;
-		end += td->len;
-		if (memchr_inv(p, 0xff, len - end))
-			return -1;
-	}
 	return 0;
 }
 
@@ -499,15 +483,9 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	else
 		numpages = 1;
 
-	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
-		/* We need only read few bytes from the OOB area */
-		scanlen = 0;
-		readlen = bd->len;
-	} else {
-		/* Full page content should be read */
-		scanlen = mtd->writesize + mtd->oobsize;
-		readlen = numpages * mtd->writesize;
-	}
+	/* We need only read few bytes from the OOB area */
+	scanlen = 0;
+	readlen = bd->len;
 
 	if (chip == -1) {
 		numblocks = mtd->size >> this->bbt_erase_shift;
@@ -869,7 +847,6 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
 {
 	struct nand_chip *this = mtd->priv;
 
-	bd->options &= ~NAND_BBT_SCANEMPTY;
 	return create_bbt(mtd, this->buffers->databuf, bd, -1);
 }
 
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index d0b169983..c4de38096 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -125,7 +125,7 @@ static struct nand_ecclayout omap_oobinfo;
  */
 static uint8_t scan_ff_pattern[] = { 0xff };
 static struct nand_bbt_descr bb_descrip_flashbased = {
-	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.options = NAND_BBT_SCANALLPAGES,
 	.offs = 0,
 	.len = 1,
 	.pattern = scan_ff_pattern,
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 211ff67e8..95fc482ce 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -93,8 +93,6 @@ struct nand_bbt_descr {
 #define NAND_BBT_CREATE_EMPTY	0x00000400
 /* Search good / bad pattern through all pages of a block */
 #define NAND_BBT_SCANALLPAGES	0x00000800
-/* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY	0x00001000
 /* Write bbt if neccecary */
 #define NAND_BBT_WRITE		0x00002000
 /* Read and write back block contents when writing bbt */
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 05/16] mtd: nand: Request strength instead of bytes for soft BCH
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (3 preceding siblings ...)
  2018-10-28 21:22 ` [PATCH 04/16] mtd: nand: remove NAND_BBT_SCANEMPTY Ladislav Michl
@ 2018-10-28 21:22 ` Ladislav Michl
  2018-10-28 21:23 ` [PATCH 06/16] mtd: atmel_nand: Add per board ECC setup Ladislav Michl
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:22 UTC (permalink / raw)
  To: barebox

Linux commits e0377cdebaf3 and 438320dd34a4 combined and adapted
for Barebox:

  Previously, we requested that drivers pass ecc.size and ecc.bytes when
  using NAND_ECC_SOFT_BCH. However, a driver is likely to only know the ECC
  strength required for its NAND, so each driver would need to perform a
  strength-to-bytes calculation.

  Avoid duplicating this calculation in each driver by asking drivers to
  pass ecc.size and ecc.strength so that the strength-to-bytes calculation
  need only be implemented once.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d4b7167f5..24fa0e3a7 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3677,15 +3677,18 @@ int nand_scan_tail(struct mtd_info *mtd)
 		chip->ecc.read_oob = nand_read_oob_std;
 		chip->ecc.write_oob = nand_write_oob_std;
 		/*
-		 * Board driver should supply ecc.size and ecc.bytes values to
-		 * select how many bits are correctable; see nand_bch_init()
-		 * for details. Otherwise, default to 4 bits for large page
-		 * devices.
+		 * Board driver should supply ecc.size and ecc.strength values
+		 * to select how many bits are correctable. Otherwise, default
+		 * to 4 bits for large page devices.
 		 */
 		if (!chip->ecc.size && (mtd->oobsize >= 64)) {
 			chip->ecc.size = 512;
-			chip->ecc.bytes = 7;
+			chip->ecc.strength = 4;
 		}
+
+		/* See nand_bch_init() for details. */
+		chip->ecc.bytes = DIV_ROUND_UP(
+				chip->ecc.strength * fls(8 * chip->ecc.size), 8);
 		chip->ecc.priv = nand_bch_init(mtd,
 					       chip->ecc.size,
 					       chip->ecc.bytes,
@@ -3694,8 +3697,6 @@ int nand_scan_tail(struct mtd_info *mtd)
 			pr_warn("BCH ECC initialization failed!\n");
 			BUG();
 		}
-		chip->ecc.strength =
-			chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
 		break;
 #endif
 #ifdef CONFIG_NAND_ECC_NONE
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 06/16] mtd: atmel_nand: Add per board ECC setup
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (4 preceding siblings ...)
  2018-10-28 21:22 ` [PATCH 05/16] mtd: nand: Request strength instead of bytes for soft BCH Ladislav Michl
@ 2018-10-28 21:23 ` Ladislav Michl
  2018-10-28 21:23 ` [PATCH 07/16] mtd: nand: simplify nand_bch_init() usage Ladislav Michl
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:23 UTC (permalink / raw)
  To: barebox

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 arch/arm/mach-at91/include/mach/board.h | 2 ++
 drivers/mtd/nand/atmel_nand.c           | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 5d76e00ae..b7adb173a 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -64,6 +64,8 @@ struct atmel_nand_data {
 	u8		cle;		/* address line number connected to CLE */
 	u8		bus_width_16;	/* buswidth is 16 bit */
 	u8		ecc_mode;	/* NAND_ECC_* */
+	u8		ecc_strength;	/* number of bits to correct per ECC step */
+	u8		ecc_size_shift;	/* data bytes covered by a single ECC step.*/
 	u8		on_flash_bbt;	/* Use flash based bbt */
 	u8		has_pmecc;	/* Use PMECC */
 	u8		bus_on_d0;
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 797cdc2ba..50c541122 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1298,6 +1298,7 @@ static int atmel_hw_nand_init_params(struct device_d *dev,
 	nand_chip->ecc.hwctl = atmel_nand_hwctl;
 	nand_chip->ecc.read_page = atmel_nand_read_page;
 	nand_chip->ecc.bytes = 4;
+	nand_chip->ecc.strength = 1;
 
 	return 0;
 }
@@ -1388,6 +1389,8 @@ static int __init atmel_nand_probe(struct device_d *dev)
 	}
 
 	nand_chip->ecc.mode = pdata->ecc_mode;
+	nand_chip->ecc.strength = pdata->ecc_strength ? : 1;
+	nand_chip->ecc.size = 1 << pdata->ecc_size_shift ? : 512;
 
 	if (IS_ENABLED(CONFIG_NAND_ECC_HW) &&
 	    pdata->ecc_mode == NAND_ECC_HW) {
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 07/16] mtd: nand: simplify nand_bch_init() usage
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (5 preceding siblings ...)
  2018-10-28 21:23 ` [PATCH 06/16] mtd: atmel_nand: Add per board ECC setup Ladislav Michl
@ 2018-10-28 21:23 ` Ladislav Michl
  2018-10-28 21:24 ` [PATCH 08/16] mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES Ladislav Michl
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:23 UTC (permalink / raw)
  To: barebox

Linux commit a8c65d504e0b modified for Barebox:

  nand_bch_init() requires several arguments which could directly be deduced
  from the mtd device. Get rid of those useless parameters.

  nand_bch_init() is also requiring the caller to provide a proper eccbytes
  value, while this value could be deduced from the ecc.size and
  ecc.strength value. Fallback to eccbytes calculation when it is set to 0.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c |  8 ++------
 drivers/mtd/nand/nand_bch.c  | 27 +++++++++++++++++----------
 include/linux/mtd/nand_bch.h |  8 ++------
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 24fa0e3a7..8faf5c587 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3687,12 +3687,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 		}
 
 		/* See nand_bch_init() for details. */
-		chip->ecc.bytes = DIV_ROUND_UP(
-				chip->ecc.strength * fls(8 * chip->ecc.size), 8);
-		chip->ecc.priv = nand_bch_init(mtd,
-					       chip->ecc.size,
-					       chip->ecc.bytes,
-					       &chip->ecc.layout);
+		chip->ecc.bytes = 0;
+		chip->ecc.priv = nand_bch_init(mtd);
 		if (!chip->ecc.priv) {
 			pr_warn("BCH ECC initialization failed!\n");
 			BUG();
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
index e37135f51..d4f2a8cbe 100644
--- a/drivers/mtd/nand/nand_bch.c
+++ b/drivers/mtd/nand/nand_bch.c
@@ -104,9 +104,6 @@ EXPORT_SYMBOL(nand_bch_correct_data);
 /**
  * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
  * @mtd:	MTD block structure
- * @eccsize:	ecc block size in bytes
- * @eccbytes:	ecc length in bytes
- * @ecclayout:	output default layout
  *
  * Returns:
  *  a pointer to a new NAND BCH control structure, or NULL upon failure
@@ -120,14 +117,21 @@ EXPORT_SYMBOL(nand_bch_correct_data);
  * @eccsize = 512  (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
  * @eccbytes = 7   (7 bytes are required to store m*t = 13*4 = 52 bits)
  */
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
-	      struct nand_ecclayout **ecclayout)
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 {
+	struct nand_chip *nand = mtd->priv;
 	unsigned int m, t, eccsteps, i;
-	struct nand_ecclayout *layout;
+	struct nand_ecclayout *layout = nand->ecc.layout;
 	struct nand_bch_control *nbc = NULL;
 	unsigned char *erased_page;
+	unsigned int eccsize = nand->ecc.size;
+	unsigned int eccbytes = nand->ecc.bytes;
+	unsigned int eccstrength = nand->ecc.strength;
+
+	if (!eccbytes && eccstrength) {
+		eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
+		nand->ecc.bytes = eccbytes;
+	}
 
 	if (!eccsize || !eccbytes) {
 		printk(KERN_WARNING "ecc parameters not supplied\n");
@@ -155,7 +159,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
 	eccsteps = mtd->writesize/eccsize;
 
 	/* if no ecc placement scheme was provided, build one */
-	if (!*ecclayout) {
+	if (!layout) {
 
 		/* handle large page devices only */
 		if (mtd->oobsize < 64) {
@@ -181,7 +185,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
 		layout->oobfree[0].offset = 2;
 		layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
 
-		*ecclayout = layout;
+		nand->ecc.layout = layout;
 	}
 
 	/* sanity checks */
@@ -189,7 +193,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
 		printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
 		goto fail;
 	}
-	if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
+	if (layout->eccbytes != (eccsteps*eccbytes)) {
 		printk(KERN_WARNING "invalid ecc layout\n");
 		goto fail;
 	}
@@ -213,6 +217,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
 	for (i = 0; i < eccbytes; i++)
 		nbc->eccmask[i] ^= 0xff;
 
+	if (!eccstrength)
+		nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
+
 	return nbc;
 fail:
 	nand_bch_free(nbc);
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h
index 61c4607fa..5465ddd13 100644
--- a/include/linux/mtd/nand_bch.h
+++ b/include/linux/mtd/nand_bch.h
@@ -32,9 +32,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,
 /*
  * Initialize BCH encoder/decoder
  */
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
-	      unsigned int eccbytes, struct nand_ecclayout **ecclayout);
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
 /*
  * Release BCH encoder/decoder resources
  */
@@ -58,9 +56,7 @@ nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
 	return -1;
 }
 
-static inline struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
-	      unsigned int eccbytes, struct nand_ecclayout **ecclayout)
+static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 {
 	return NULL;
 }
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 08/16] mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (6 preceding siblings ...)
  2018-10-28 21:23 ` [PATCH 07/16] mtd: nand: simplify nand_bch_init() usage Ladislav Michl
@ 2018-10-28 21:24 ` Ladislav Michl
  2018-10-28 21:24 ` [PATCH 09/16] mtd: nand_bbt: handle error case for nand_create_badblock_pattern() Ladislav Michl
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:24 UTC (permalink / raw)
  To: barebox

Linux commit 5961ad2cb4dd adapted for Barebox:

  Now that the last user of NAND_BBT_SCANALLPAGES has been removed, let's
  kill this peculiar BBT feature flag.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c       | 37 +++----------------------------
 drivers/mtd/nand/nand_omap_gpmc.c |  1 -
 include/linux/mtd/bbm.h           |  2 --
 3 files changed, 3 insertions(+), 37 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 19888589f..e296fe204 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -404,25 +404,6 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 	}
 }
 
-/* Scan a given block full */
-static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
-			   loff_t offs, uint8_t *buf, size_t readlen,
-			   int scanlen, int numpages)
-{
-	int ret, j;
-
-	ret = scan_read_oob(mtd, buf, offs, readlen);
-	/* Ignore ECC errors when checking for BBM */
-	if (ret && !mtd_is_bitflip_or_eccerr(ret))
-		return ret;
-
-	for (j = 0; j < numpages; j++, buf += scanlen) {
-		if (check_pattern(buf, scanlen, mtd->writesize, bd))
-			return 1;
-	}
-	return 0;
-}
-
 /* Scan a given block partially */
 static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 			   loff_t offs, uint8_t *buf, int numpages)
@@ -469,24 +450,17 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *bd, int chip)
 {
 	struct nand_chip *this = mtd->priv;
-	int i, numblocks, numpages, scanlen;
+	int i, numblocks, numpages;
 	int startblock;
 	loff_t from;
-	size_t readlen;
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if (bd->options & NAND_BBT_SCANALLPAGES)
-		numpages = 1 << (this->bbt_erase_shift - this->page_shift);
-	else if (bd->options & NAND_BBT_SCAN2NDPAGE)
+	if (bd->options & NAND_BBT_SCAN2NDPAGE)
 		numpages = 2;
 	else
 		numpages = 1;
 
-	/* We need only read few bytes from the OOB area */
-	scanlen = 0;
-	readlen = bd->len;
-
 	if (chip == -1) {
 		numblocks = mtd->size >> this->bbt_erase_shift;
 		startblock = 0;
@@ -511,12 +485,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
 
-		if (bd->options & NAND_BBT_SCANALLPAGES)
-			ret = scan_block_full(mtd, bd, from, buf, readlen,
-					      scanlen, numpages);
-		else
-			ret = scan_block_fast(mtd, bd, from, buf, numpages);
-
+		ret = scan_block_fast(mtd, bd, from, buf, numpages);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index c4de38096..91c2a7a9b 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -125,7 +125,6 @@ static struct nand_ecclayout omap_oobinfo;
  */
 static uint8_t scan_ff_pattern[] = { 0xff };
 static struct nand_bbt_descr bb_descrip_flashbased = {
-	.options = NAND_BBT_SCANALLPAGES,
 	.offs = 0,
 	.len = 1,
 	.pattern = scan_ff_pattern,
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 95fc482ce..36bb6a503 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -91,8 +91,6 @@ struct nand_bbt_descr {
  * with NAND_BBT_CREATE.
  */
 #define NAND_BBT_CREATE_EMPTY	0x00000400
-/* Search good / bad pattern through all pages of a block */
-#define NAND_BBT_SCANALLPAGES	0x00000800
 /* Write bbt if neccecary */
 #define NAND_BBT_WRITE		0x00002000
 /* Read and write back block contents when writing bbt */
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 09/16] mtd: nand_bbt: handle error case for nand_create_badblock_pattern()
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (7 preceding siblings ...)
  2018-10-28 21:24 ` [PATCH 08/16] mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES Ladislav Michl
@ 2018-10-28 21:24 ` Ladislav Michl
  2018-10-28 21:25 ` [PATCH 10/16] mtd: nand_bbt: make nand_scan_bbt() static Ladislav Michl
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:24 UTC (permalink / raw)
  To: barebox

Linux commit abb9cf78e80a adapted for Barebox.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index e296fe204..360cfcd7e 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1272,6 +1272,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
 int nand_default_bbt(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
+	int ret;
 
 	/* Is a flash based bad block table requested? */
 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
@@ -1290,8 +1291,11 @@ int nand_default_bbt(struct mtd_info *mtd)
 		this->bbt_md = NULL;
 	}
 
-	if (!this->badblock_pattern)
-		nand_create_badblock_pattern(this);
+	if (!this->badblock_pattern) {
+		ret = nand_create_badblock_pattern(this);
+		if (ret)
+			return ret;
+	}
 
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 10/16] mtd: nand_bbt: make nand_scan_bbt() static
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (8 preceding siblings ...)
  2018-10-28 21:24 ` [PATCH 09/16] mtd: nand_bbt: handle error case for nand_create_badblock_pattern() Ladislav Michl
@ 2018-10-28 21:25 ` Ladislav Michl
  2018-10-28 21:25 ` [PATCH 11/16] mtd: nand_bbt: unify/fix error handling in nand_scan_bbt() Ladislav Michl
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:25 UTC (permalink / raw)
  To: barebox

Linux commit 17799359e7b adapted for Barebox:

  This implementation detail is no longer needed outside of nand_bbt.c.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 2 +-
 include/linux/mtd/nand.h    | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 360cfcd7e..e12f65a92 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1067,7 +1067,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
  * The bad block table memory is allocated here. It must be freed by calling
  * the nand_free_bbt function.
  */
-int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
 	int len, res = 0;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8caf5edec..ed70c18a1 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -634,7 +634,6 @@ struct nand_manufacturers {
 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);
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 11/16] mtd: nand_bbt: unify/fix error handling in nand_scan_bbt()
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (9 preceding siblings ...)
  2018-10-28 21:25 ` [PATCH 10/16] mtd: nand_bbt: make nand_scan_bbt() static Ladislav Michl
@ 2018-10-28 21:25 ` Ladislav Michl
  2018-10-28 21:25 ` [PATCH 12/16] mtd: nand_bbt: Move BBT block selection logic out of write_bbt() Ladislav Michl
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:25 UTC (permalink / raw)
  To: barebox

Linux commit 83c59542d0af adapted for Barebox:

  Don't leak this->bbt, and return early if check_create() fails. It helps
  to have a single error path to avoid these problems.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index e12f65a92..bcd54d7a9 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1070,7 +1070,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
-	int len, res = 0;
+	int len, res;
 	uint8_t *buf;
 	struct nand_bbt_descr *td = this->bbt_td;
 	struct nand_bbt_descr *md = this->bbt_md;
@@ -1091,10 +1091,9 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
 			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
-			kfree(this->bbt);
-			this->bbt = NULL;
+			goto err;
 		}
-		return res;
+		return 0;
 	}
 	verify_bbt_descr(mtd, td);
 	verify_bbt_descr(mtd, md);
@@ -1104,9 +1103,8 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = vmalloc(len);
 	if (!buf) {
-		kfree(this->bbt);
-		this->bbt = NULL;
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto err;
 	}
 
 	/* Is the bbt at a given page? */
@@ -1118,6 +1116,8 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	}
 
 	res = check_create(mtd, buf, bd);
+	if (res)
+		goto err;
 
 	/* Prevent the bbt regions from erasing / writing */
 	mark_bbt_region(mtd, td);
@@ -1125,6 +1125,11 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 		mark_bbt_region(mtd, md);
 
 	vfree(buf);
+	return 0;
+
+err:
+	kfree(this->bbt);
+	this->bbt = NULL;
 	return res;
 }
 
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 12/16] mtd: nand_bbt: Move BBT block selection logic out of write_bbt()
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (10 preceding siblings ...)
  2018-10-28 21:25 ` [PATCH 11/16] mtd: nand_bbt: unify/fix error handling in nand_scan_bbt() Ladislav Michl
@ 2018-10-28 21:25 ` Ladislav Michl
  2018-10-28 21:26 ` [PATCH 13/16] mtd: nand_bbt: scan for next free bbt block if writing bbt fails Ladislav Michl
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:25 UTC (permalink / raw)
  To: barebox

Linux commit c3baf278d3bf adapted for Barebox:

  This clarifies the write_bbt() function by removing the write label
  and simplifying the error/exit path.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 110 ++++++++++++++++++++++++------------
 1 file changed, 74 insertions(+), 36 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index bcd54d7a9..1d3551b4e 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -599,6 +599,69 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
 		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
  * @mtd: MTD device structure
@@ -616,7 +679,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	struct nand_chip *this = mtd->priv;
 	struct erase_info einfo;
 	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;
 	uint8_t msk[4];
 	uint8_t rcode = td->reserved_block_code;
@@ -648,45 +711,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 	/* Loop through the chips */
 	for (; chip < nrchips; chip++) {
-		/*
-		 * There was already a version of the table, reuse the page
-		 * This applies for absolute placement too, as we have the
-		 * page nr. in td->pages.
-		 */
-		if (td->pages[chip] != -1) {
-			page = td->pages[chip];
-			goto write;
+		int block;
+
+		block = get_bbt_block(this, td, md, chip);
+		if (block < 0) {
+			pr_err("No space left to write bad block table\n");
+			res = block;
+			goto outerr;
 		}
 
 		/*
-		 * Automatic placement of the bad block table. Search direction
-		 * top -> down?
+		 * get_bbt_block() returns a block number, shift the value to
+		 * get a page number.
 		 */
-		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)
-				goto write;
-		}
-		pr_err("No space left to write bad block table\n");
-		return -ENOSPC;
-	write:
+		page = block << (this->bbt_erase_shift - this->page_shift);
 
 		/* Set up shift count and masks for the flash table */
 		bits = td->options & NAND_BBT_NRBITS_MSK;
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 13/16] mtd: nand_bbt: scan for next free bbt block if writing bbt fails
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (11 preceding siblings ...)
  2018-10-28 21:25 ` [PATCH 12/16] mtd: nand_bbt: Move BBT block selection logic out of write_bbt() Ladislav Michl
@ 2018-10-28 21:26 ` Ladislav Michl
  2018-10-28 21:26 ` [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook Ladislav Michl
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:26 UTC (permalink / raw)
  To: barebox

Linux commit 10ffd570f117 adapted for Barebox:

  If erasing or writing the BBT fails, we should mark the current BBT
  block as bad and use the BBT descriptor to scan for the next available
  unused block in the BBT. We should only return a failure if there isn't
  any space left.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_bbt.c | 51 ++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 1d3551b4e..af992e795 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -662,6 +662,37 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
 	return -ENOSPC;
 }
 
+/**
+ * mark_bbt_block_bad - Mark one of the block reserved for BBT bad
+ * @mtd: the MTD device
+ * @td: the BBT description
+ * @chip: the CHIP selector
+ * @block: the BBT block to mark
+ *
+ * Blocks reserved for BBT can become bad. This functions is an helper to mark
+ * such blocks as bad. It takes care of updating the in-memory BBT, marking the
+ * block as bad using a bad block marker and invalidating the associated
+ * td->pages[] entry.
+ */
+static void mark_bbt_block_bad(struct mtd_info *mtd,
+			       struct nand_bbt_descr *td,
+			       int chip, int block)
+{
+	struct nand_chip *this = mtd->priv;
+	loff_t to;
+	int res;
+
+	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+
+	to = (loff_t)block << this->bbt_erase_shift;
+	res = this->block_markbad(mtd, to);
+	if (res)
+		pr_warn("nand_bbt: error %d while marking block %d bad\n",
+			res, block);
+
+	td->pages[chip] = -1;
+}
+
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
  * @mtd: MTD device structure
@@ -710,7 +741,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	}
 
 	/* Loop through the chips */
-	for (; chip < nrchips; chip++) {
+	while (chip < nrchips) {
 		int block;
 
 		block = get_bbt_block(this, td, md, chip);
@@ -820,20 +851,28 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		einfo.addr = to;
 		einfo.len = 1 << this->bbt_erase_shift;
 		res = nand_erase_nand(mtd, &einfo, 1);
-		if (res < 0)
-			goto outerr;
+		if (res < 0) {
+			pr_warn("nand_bbt: error while erasing BBT block %d\n",
+				res);
+			mark_bbt_block_bad(mtd, td, chip, block);
+			continue;
+		}
 
 		res = scan_write_bbt(mtd, to, len, buf,
 				td->options & NAND_BBT_NO_OOB ? NULL :
 				&buf[len]);
-		if (res < 0)
-			goto outerr;
+		if (res < 0) {
+			pr_warn("nand_bbt: error while writing BBT block %d\n",
+				res);
+			mark_bbt_block_bad(mtd, td, chip, block);
+			continue;
+		}
 
 		pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
 			 (unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
-		td->pages[chip] = page;
+		td->pages[chip++] = page;
 	}
 	return 0;
 
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (12 preceding siblings ...)
  2018-10-28 21:26 ` [PATCH 13/16] mtd: nand_bbt: scan for next free bbt block if writing bbt fails Ladislav Michl
@ 2018-10-28 21:26 ` Ladislav Michl
  2019-01-21  8:32   ` Sascha Hauer
  2018-10-28 21:27 ` [PATCH 15/16] mtd: nand: Kill cellinfo Ladislav Michl
  2018-10-28 21:27 ` [PATCH 16/16] mtd: nand: detect OOB size for Toshiba 24nm raw SLC Ladislav Michl
  15 siblings, 1 reply; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:26 UTC (permalink / raw)
  To: barebox

Linux commit e80eba758151 adapted for Barebox:

  None of the existing drivers are overloading the ->scan_bbt()
  method, let's get rid of it and replace calls to ->scan_bbt()
  by nand_create_bbt() ones.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c    |  6 +-----
 drivers/mtd/nand/nand_bbt.c     |  9 +++++----
 drivers/mtd/nand/nand_imx_bbm.c |  2 +-
 drivers/mtd/nand/nand_mxs.c     | 27 +++++++++------------------
 include/linux/mtd/nand.h        |  5 +----
 5 files changed, 17 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 8faf5c587..e20831a2c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2935,10 +2935,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 #endif
 	if (!chip->read_buf)
 		chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
-#ifdef CONFIG_NAND_BBT
-	if (!chip->scan_bbt)
-		chip->scan_bbt = nand_default_bbt;
-#endif
 	if (!chip->controller) {
 		chip->controller = &chip->hwcontrol;
 	}
@@ -3804,7 +3800,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		return 0;
 
 	/* Build bad block table */
-	return chip->scan_bbt(mtd);
+	return nand_create_bbt(mtd);
 }
 EXPORT_SYMBOL(nand_scan_tail);
 
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index af992e795..b4f3b7e95 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -77,6 +77,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];
@@ -1217,7 +1219,7 @@ err:
  *
  * 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;
@@ -1345,13 +1347,13 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
 }
 
 /**
- * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
+ * nand_create_bbt - [NAND Interface] Select a default bad block table for the device
  * @mtd: MTD device structure
  *
  * This function selects the default bad block table support for the device and
  * calls the nand_scan_bbt function.
  */
-int nand_default_bbt(struct mtd_info *mtd)
+int nand_create_bbt(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 	int ret;
@@ -1450,4 +1452,3 @@ int nand_markgood_bbt(struct mtd_info *mtd, loff_t offs)
 
 EXPORT_SYMBOL(nand_scan_bbt);
 EXPORT_SYMBOL(nand_default_bbt);
-EXPORT_SYMBOL_GPL(nand_update_bbt);
diff --git a/drivers/mtd/nand/nand_imx_bbm.c b/drivers/mtd/nand/nand_imx_bbm.c
index 23722a906..4fd5487aa 100644
--- a/drivers/mtd/nand/nand_imx_bbm.c
+++ b/drivers/mtd/nand/nand_imx_bbm.c
@@ -129,7 +129,7 @@ static int attach_bbt(struct mtd_info *mtd, void *bbt)
 	free(chip->bbt);
 	chip->bbt = bbt;
 
-	return nand_update_bbt(mtd, 0);
+	return nand_create_bbt(mtd);
 }
 
 static int do_imx_nand_bbm(int argc, char *argv[])
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 28a07d4cb..f69453aba 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -1201,21 +1201,7 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	return 0;
 }
 
-/*
- * Nominally, the purpose of this function is to look for or create the bad
- * block table. In fact, since the we call this function at the very end of
- * the initialization process started by nand_scan(), and we doesn't have a
- * more formal mechanism, we "hook" this function to continue init process.
- *
- * At this point, the physical NAND Flash chips have been identified and
- * counted, so we know the physical geometry. This enables us to make some
- * important configuration decisions.
- *
- * The return value of this function propogates directly back to this driver's
- * call to nand_scan(). Anything other than zero will cause this driver to
- * tear everything down and declare failure.
- */
-static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+static int mxs_nand_init_bch(struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd->priv;
 	struct mxs_nand_info *nand_info = nand->priv;
@@ -1252,8 +1238,7 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
 		mtd->block_markbad = mxs_nand_hook_block_markbad;
 	}
 
-	/* We use the reference implementation for bad block management. */
-	return nand_default_bbt(mtd);
+	return 0;
 }
 
 /*
@@ -2183,7 +2168,6 @@ static int mxs_nand_probe(struct device_d *dev)
 	nand->dev_ready		= mxs_nand_device_ready;
 	nand->select_chip	= mxs_nand_select_chip;
 	nand->block_bad		= mxs_nand_block_bad;
-	nand->scan_bbt		= mxs_nand_scan_bbt;
 
 	nand->read_byte		= mxs_nand_read_byte;
 
@@ -2215,6 +2199,13 @@ static int mxs_nand_probe(struct device_d *dev)
 
 	mxs_nand_setup_timing(nand_info);
 
+	err = mxs_nand_init_bch(mtd);
+	if (err)
+		goto err2;
+	err = nand_create_bbt(mtd);
+	if (err)
+		goto err2;
+
 	/* second phase scan */
 	err = nand_scan_tail(mtd);
 	if (err)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ed70c18a1..e1c7837a8 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -417,7 +417,6 @@ struct nand_buffers {
  * @hwcontrol:		platform-specific hardware control structure
  * @erase_cmd:		[INTERN] erase command write function, selectable due
  *			to AND support.
- * @scan_bbt:		[REPLACEABLE] function to scan bad block table
  * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transferring
  *			data from array to read regs (tR).
  * @state:		[INTERN] the current state of the NAND device
@@ -491,7 +490,6 @@ struct nand_chip {
 			int page_addr);
 	int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
 	void (*erase_cmd)(struct mtd_info *mtd, int page);
-	int (*scan_bbt)(struct mtd_info *mtd);
 	int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
 			int status, int page);
 	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -634,8 +632,7 @@ struct nand_manufacturers {
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_create_bbt(struct mtd_info *mtd);
 extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_markgood_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 15/16] mtd: nand: Kill cellinfo
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (13 preceding siblings ...)
  2018-10-28 21:26 ` [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook Ladislav Michl
@ 2018-10-28 21:27 ` Ladislav Michl
  2018-10-28 21:27 ` [PATCH 16/16] mtd: nand: detect OOB size for Toshiba 24nm raw SLC Ladislav Michl
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:27 UTC (permalink / raw)
  To: barebox

The only information used from cellinfo field is whenever flash is SLC
or MLC, therefore eliminate it completely. This patch is based on Linux
commit 7db906b79f69.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c | 29 ++++++++++++++++++++---------
 include/linux/mtd/nand.h     |  3 +--
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e20831a2c..9b2d3f1cf 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3098,6 +3098,16 @@ static int nand_id_len(u8 *id_data, int arrlen)
 	return arrlen;
 }
 
+/* Extract the bits of per cell from the 3rd byte of the extended ID */
+static int nand_get_bits_per_cell(u8 cellinfo)
+{
+	int bits;
+
+	bits = cellinfo & NAND_CI_CELLTYPE_MSK;
+	bits >>= NAND_CI_CELLTYPE_SHIFT;
+	return bits + 1;
+}
+
 /*
  * Many new NAND share similar device ID codes, which represent the size of the
  * chip. The rest of the parameters must be decoded according to generic or
@@ -3108,7 +3118,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 {
 	int extid, id_len;
 	/* The 3rd id byte holds MLC / multichip data */
-	chip->cellinfo = id_data[2];
+	chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
 	/* The 4th id byte is the important one */
 	extid = id_data[3];
 
@@ -3124,8 +3134,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 	 * ID to decide what to do.
 	 */
 	if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
-			(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
-			id_data[5] != 0x00) {
+			!nand_is_slc(chip) && id_data[5] != 0x00) {
 		/* Calc pagesize */
 		mtd->writesize = 2048 << (extid & 0x03);
 		extid >>= 2;
@@ -3157,7 +3166,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 			(((extid >> 1) & 0x04) | (extid & 0x03));
 		*busw = 0;
 	} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
-			(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+			!nand_is_slc(chip)) {
 		unsigned int tmp;
 
 		/* Calc pagesize */
@@ -3229,6 +3238,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
 	mtd->oobsize = mtd->writesize / 32;
 	*busw = type->options & NAND_BUSWIDTH_16;
 
+	/* All legacy ID NAND are small-page, SLC */
+	chip->bits_per_cell = 1;
+
 	/*
 	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
 	 * some Spansion chips have erasesize that conflicts with size
@@ -3265,11 +3277,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
-	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+	if (!nand_is_slc(chip) &&
 			(maf_id == NAND_MFR_SAMSUNG ||
 			 maf_id == NAND_MFR_HYNIX))
 		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
-	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+	else if ((nand_is_slc(chip) &&
 				(maf_id == NAND_MFR_SAMSUNG ||
 				 maf_id == NAND_MFR_HYNIX ||
 				 maf_id == NAND_MFR_TOSHIBA ||
@@ -3293,7 +3305,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 		mtd->erasesize = type->erasesize;
 		mtd->oobsize = type->oobsize;
 
-		chip->cellinfo = id_data[2];
+		chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
 		chip->chipsize = (uint64_t)type->chipsize << 20;
 		chip->options |= type->options;
 
@@ -3739,8 +3751,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
 	/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
-	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
-	    !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
 		switch (chip->ecc.steps) {
 		case 2:
 			mtd->subpage_sft = 1;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index e1c7837a8..c3eb16f90 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -203,6 +203,7 @@ typedef enum {
 /* Cell info constants */
 #define NAND_CI_CHIPNR_MSK	0x03
 #define NAND_CI_CELLTYPE_MSK	0x0C
+#define NAND_CI_CELLTYPE_SHIFT	2
 
 /* Keep gcc happy */
 struct nand_chip;
@@ -439,7 +440,6 @@ struct nand_buffers {
  *			bad block marker position; i.e., BBM == 11110111b is
  *			not bad when badblockbits == 7
  * @bits_per_cell:	[INTERN] number of bits per cell. i.e., 1 means SLC.
- * @cellinfo:		[INTERN] MLC/multichip data from chip ident
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
@@ -515,7 +515,6 @@ struct nand_chip {
 	unsigned int pagebuf_bitflips;
 	int subpagesize;
 	uint8_t bits_per_cell;
-	uint8_t cellinfo;
 	int badblockpos;
 	int badblockbits;
 
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 16/16] mtd: nand: detect OOB size for Toshiba 24nm raw SLC
  2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
                   ` (14 preceding siblings ...)
  2018-10-28 21:27 ` [PATCH 15/16] mtd: nand: Kill cellinfo Ladislav Michl
@ 2018-10-28 21:27 ` Ladislav Michl
  15 siblings, 0 replies; 21+ messages in thread
From: Ladislav Michl @ 2018-10-28 21:27 UTC (permalink / raw)
  To: barebox

Linux commit 60c673824561.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 drivers/mtd/nand/nand_base.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9b2d3f1cf..e290081bb 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3219,6 +3219,20 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		extid >>= 2;
 		/* Get buswidth information */
 		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+		/*
+		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+		 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+		 * follows:
+		 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+		 *                         110b -> 24nm
+		 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
+		 */
+		if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
+				nand_is_slc(chip) &&
+				(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
+				!(id_data[4] & 0x80) /* !BENAND */) {
+			mtd->oobsize = 32 * mtd->writesize >> 9;
+		}
 	}
 }
 
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details
  2018-10-28 21:22 ` [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details Ladislav Michl
@ 2018-10-29 10:07   ` Ladislav Michl
  2018-10-29 11:43     ` Ladislav Michl
  0 siblings, 1 reply; 21+ messages in thread
From: Ladislav Michl @ 2018-10-29 10:07 UTC (permalink / raw)
  To: barebox

On Sun, Oct 28, 2018 at 10:22:13PM +0100, Ladislav Michl wrote:
> Linux commit b32843b772db adapted for Barebox:

Hmm, there's something fishy with markgood functions (trying different board).
Debugging now...

>   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).

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details
  2018-10-29 10:07   ` Ladislav Michl
@ 2018-10-29 11:43     ` Ladislav Michl
  2018-10-30  9:07       ` Sascha Hauer
  0 siblings, 1 reply; 21+ messages in thread
From: Ladislav Michl @ 2018-10-29 11:43 UTC (permalink / raw)
  To: barebox

On Mon, Oct 29, 2018 at 11:07:02AM +0100, Ladislav Michl wrote:
> On Sun, Oct 28, 2018 at 10:22:13PM +0100, Ladislav Michl wrote:
> > Linux commit b32843b772db adapted for Barebox:
> 
> Hmm, there's something fishy with markgood functions (trying different board).
> Debugging now...
> 
> >   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).

Two bugs spotted:
1) we need to select chip again after erase
2) Linux cares only about marking block bad in BBT while Barebox supports
   also unmarking it. Thus we need a bit more complicated version of
   bbt_mark_entry.

Incremental patch bellow. Please let me know if there are another issues
with this serie, I'll squash it for v2.

Thank you.

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e290081bb..6004f423b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -447,8 +447,11 @@ static int nand_block_markgood_lowlevel(struct mtd_info *mtd, loff_t ofs)
 		nand_erase_nand(mtd, &einfo, 0);
 		mtd->allow_erasebad = allow_erasebad;
 
-		/* Still bad? */
-		ret = chip->block_bad(mtd, ofs, 0);
+		/*
+		 * Verify erase succeded. We need to select chip again,
+		 * as nand_erase_nand deselected it.
+		 */
+		ret = chip->block_bad(mtd, ofs, 1);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b4f3b7e95..65870d3ec 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -89,8 +89,14 @@ static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
 static inline void bbt_mark_entry(struct nand_chip *chip, int block,
 		uint8_t mark)
 {
-	uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2);
-	chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk;
+	/*
+	 * Unlike original Linux implementation, Barebox needs also
+	 * mark block as good again, so mask entry comletely.
+	 */
+	int index = block >> BBT_ENTRY_SHIFT;
+	int shift = (block & BBT_ENTRY_MASK) * 2;
+	chip->bbt[index] &= ~(BBT_ENTRY_MASK << shift);
+	chip->bbt[index] |= (mark & BBT_ENTRY_MASK) << shift;
 }
 
 static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details
  2018-10-29 11:43     ` Ladislav Michl
@ 2018-10-30  9:07       ` Sascha Hauer
  0 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2018-10-30  9:07 UTC (permalink / raw)
  To: Ladislav Michl; +Cc: barebox

On Mon, Oct 29, 2018 at 12:43:29PM +0100, Ladislav Michl wrote:
> On Mon, Oct 29, 2018 at 11:07:02AM +0100, Ladislav Michl wrote:
> > On Sun, Oct 28, 2018 at 10:22:13PM +0100, Ladislav Michl wrote:
> > > Linux commit b32843b772db adapted for Barebox:
> > 
> > Hmm, there's something fishy with markgood functions (trying different board).
> > Debugging now...
> > 
> > >   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).
> 
> Two bugs spotted:
> 1) we need to select chip again after erase
> 2) Linux cares only about marking block bad in BBT while Barebox supports
>    also unmarking it. Thus we need a bit more complicated version of
>    bbt_mark_entry.
> 
> Incremental patch bellow. Please let me know if there are another issues
> with this serie, I'll squash it for v2.

I had a look over the series, but it's very hard to do a proper review
without spending a lot of time. I guess I just have to believe that
these are Linux commits and thus are good and valuable for barebox
aswell ;)

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook
  2018-10-28 21:26 ` [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook Ladislav Michl
@ 2019-01-21  8:32   ` Sascha Hauer
  0 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2019-01-21  8:32 UTC (permalink / raw)
  To: Ladislav Michl; +Cc: barebox

On Sun, Oct 28, 2018 at 10:26:38PM +0100, Ladislav Michl wrote:
> Linux commit e80eba758151 adapted for Barebox:
> 
>   None of the existing drivers are overloading the ->scan_bbt()
>   method, let's get rid of it and replace calls to ->scan_bbt()
>   by nand_create_bbt() ones.
> 
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> ---
> diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
> index 28a07d4cb..f69453aba 100644
> --- a/drivers/mtd/nand/nand_mxs.c
> +++ b/drivers/mtd/nand/nand_mxs.c
> @@ -1201,21 +1201,7 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
>  	return 0;
>  }
>  
> -/*
> - * Nominally, the purpose of this function is to look for or create the bad
> - * block table. In fact, since the we call this function at the very end of
> - * the initialization process started by nand_scan(), and we doesn't have a
> - * more formal mechanism, we "hook" this function to continue init process.
> - *
> - * At this point, the physical NAND Flash chips have been identified and
> - * counted, so we know the physical geometry. This enables us to make some
> - * important configuration decisions.
> - *
> - * The return value of this function propogates directly back to this driver's
> - * call to nand_scan(). Anything other than zero will cause this driver to
> - * tear everything down and declare failure.
> - */
> -static int mxs_nand_scan_bbt(struct mtd_info *mtd)
> +static int mxs_nand_init_bch(struct mtd_info *mtd)
>  {
>  	struct nand_chip *nand = mtd->priv;
>  	struct mxs_nand_info *nand_info = nand->priv;
> @@ -1252,8 +1238,7 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
>  		mtd->block_markbad = mxs_nand_hook_block_markbad;
>  	}
>  
> -	/* We use the reference implementation for bad block management. */
> -	return nand_default_bbt(mtd);
> +	return 0;
>  }
>  
>  /*
> @@ -2183,7 +2168,6 @@ static int mxs_nand_probe(struct device_d *dev)
>  	nand->dev_ready		= mxs_nand_device_ready;
>  	nand->select_chip	= mxs_nand_select_chip;
>  	nand->block_bad		= mxs_nand_block_bad;
> -	nand->scan_bbt		= mxs_nand_scan_bbt;
>  
>  	nand->read_byte		= mxs_nand_read_byte;
>  
> @@ -2215,6 +2199,13 @@ static int mxs_nand_probe(struct device_d *dev)
>  
>  	mxs_nand_setup_timing(nand_info);
>  
> +	err = mxs_nand_init_bch(mtd);
> +	if (err)
> +		goto err2;
> +	err = nand_create_bbt(mtd);
> +	if (err)
> +		goto err2;
> +

By the time nand_create_bbt() is called mtd->read is not yet set, so we
end up with a NULL pointer deref here.

>  	/* second phase scan */
>  	err = nand_scan_tail(mtd);

This call sets mtd->read, so we can call nand_create_bbt() only after
it.

The MXS nand driver plays some funny tricks, so the correct fix is non
obvious to me.

I reverted this patch for now.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2019-01-21  8:32 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-28 21:19 [PATCH 00/16] NAND update (1st step) Ladislav Michl
2018-10-28 21:21 ` [PATCH 01/16] mtd: nand: refactor chip->block_markbad interface Ladislav Michl
2018-10-28 21:21 ` [PATCH 02/16] mtd: nand: remove multiplied-by-2 block logic Ladislav Michl
2018-10-28 21:22 ` [PATCH 03/16] mtd: nand: hide in-memory BBT implementation details Ladislav Michl
2018-10-29 10:07   ` Ladislav Michl
2018-10-29 11:43     ` Ladislav Michl
2018-10-30  9:07       ` Sascha Hauer
2018-10-28 21:22 ` [PATCH 04/16] mtd: nand: remove NAND_BBT_SCANEMPTY Ladislav Michl
2018-10-28 21:22 ` [PATCH 05/16] mtd: nand: Request strength instead of bytes for soft BCH Ladislav Michl
2018-10-28 21:23 ` [PATCH 06/16] mtd: atmel_nand: Add per board ECC setup Ladislav Michl
2018-10-28 21:23 ` [PATCH 07/16] mtd: nand: simplify nand_bch_init() usage Ladislav Michl
2018-10-28 21:24 ` [PATCH 08/16] mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES Ladislav Michl
2018-10-28 21:24 ` [PATCH 09/16] mtd: nand_bbt: handle error case for nand_create_badblock_pattern() Ladislav Michl
2018-10-28 21:25 ` [PATCH 10/16] mtd: nand_bbt: make nand_scan_bbt() static Ladislav Michl
2018-10-28 21:25 ` [PATCH 11/16] mtd: nand_bbt: unify/fix error handling in nand_scan_bbt() Ladislav Michl
2018-10-28 21:25 ` [PATCH 12/16] mtd: nand_bbt: Move BBT block selection logic out of write_bbt() Ladislav Michl
2018-10-28 21:26 ` [PATCH 13/16] mtd: nand_bbt: scan for next free bbt block if writing bbt fails Ladislav Michl
2018-10-28 21:26 ` [PATCH 14/16] mtd: nand: Kill the chip->scan_bbt() hook Ladislav Michl
2019-01-21  8:32   ` Sascha Hauer
2018-10-28 21:27 ` [PATCH 15/16] mtd: nand: Kill cellinfo Ladislav Michl
2018-10-28 21:27 ` [PATCH 16/16] mtd: nand: detect OOB size for Toshiba 24nm raw SLC Ladislav Michl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox