All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] mtd: rawnand: Support bad block markers in first, second or last page
@ 2019-02-18 10:42 ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: linux-mtd, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Currently supported bad block marker positions within the block are:
* in first page only
* in last page only
* in first or second page

After some cleanup and preparation in patch 1 and 2, we make it
possible to set NAND_BBM_FIRSTPAGE, NAND_BBM_SECONDPAGE and
NAND_BBM_LASTPAGE independently of each other (patch 3).

Some ESMT NANDs are known to have been shipped by the manufacturer
with bad block markers in the first or last page, instead of the
first or second page.

Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
first, second *and* last page needs to be checked.

Therefore in patch 4 and 5 we set all three flags for
AMD/Spansion/Cypress and ESMT chips.
---
Changes in v4:
==============
* Move onenand changes to separate patch
* Add missing badblockpos field to onenand_chip struct
* Move cleanup of badblockpos field and flags to separate patch
* Move assignemnt of badblockpos from onenand_bbt.c to onenand_base.c
* Fix incorrect usage of bbt_options in nand_bbt.c
* Add R-b tags

Changes in v3:
==============
* Fix bit offsets for new flags in nand_chip->options
* Move separation of flags for first and second page markers to a
  separate patch
* Fix cover letter
* Fix S-o-b tag
* Add R-b tags

Changes in v2:
==============
* Rebase on 5.0-rc1
* Add patch to move bad block marker position info to a common place and
  rename/prepare existing flags
* improve/rename function nand_bbm_get_next_page() to use new flags
---
Frieder Schrempf (7):
  mtd: rawnand: Always store info about bad block markers in chip struct
  mtd: onenand: Store bad block marker position in chip struct
  mtd: nand: Cleanup flags and fields for bad block marker position
  mtd: nand: Make flags for bad block marker position more granular
  mtd: rawnand: Support bad block markers in first, second or last page
  mtd: rawnand: ESMT: Also use the last page for bad block markers
  mtd: rawnand: AMD: Also use the last page for bad block markers

 drivers/mtd/nand/onenand/onenand_base.c |  5 +-
 drivers/mtd/nand/onenand/onenand_bbt.c  |  3 --
 drivers/mtd/nand/raw/internals.h        |  1 +
 drivers/mtd/nand/raw/nand_amd.c         |  8 +++-
 drivers/mtd/nand/raw/nand_base.c        | 64 +++++++++++++++++--------
 drivers/mtd/nand/raw/nand_bbt.c         | 28 +++++------
 drivers/mtd/nand/raw/nand_esmt.c        |  9 +++-
 drivers/mtd/nand/raw/nand_hynix.c       |  4 +-
 drivers/mtd/nand/raw/nand_macronix.c    |  2 +-
 drivers/mtd/nand/raw/nand_micron.c      |  2 +-
 drivers/mtd/nand/raw/nand_samsung.c     |  4 +-
 drivers/mtd/nand/raw/nand_toshiba.c     |  2 +-
 drivers/mtd/nand/raw/sh_flctl.c         |  4 +-
 include/linux/mtd/bbm.h                 | 14 +-----
 include/linux/mtd/onenand.h             |  3 ++
 include/linux/mtd/rawnand.h             | 15 ++++++
 16 files changed, 104 insertions(+), 64 deletions(-)

-- 
2.17.1

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

* [PATCH v4 0/7] mtd: rawnand: Support bad block markers in first, second or last page
@ 2019-02-18 10:42 ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: linux-mtd, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Currently supported bad block marker positions within the block are:
* in first page only
* in last page only
* in first or second page

After some cleanup and preparation in patch 1 and 2, we make it
possible to set NAND_BBM_FIRSTPAGE, NAND_BBM_SECONDPAGE and
NAND_BBM_LASTPAGE independently of each other (patch 3).

Some ESMT NANDs are known to have been shipped by the manufacturer
with bad block markers in the first or last page, instead of the
first or second page.

Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
first, second *and* last page needs to be checked.

Therefore in patch 4 and 5 we set all three flags for
AMD/Spansion/Cypress and ESMT chips.
---
Changes in v4:
==============
* Move onenand changes to separate patch
* Add missing badblockpos field to onenand_chip struct
* Move cleanup of badblockpos field and flags to separate patch
* Move assignemnt of badblockpos from onenand_bbt.c to onenand_base.c
* Fix incorrect usage of bbt_options in nand_bbt.c
* Add R-b tags

Changes in v3:
==============
* Fix bit offsets for new flags in nand_chip->options
* Move separation of flags for first and second page markers to a
  separate patch
* Fix cover letter
* Fix S-o-b tag
* Add R-b tags

Changes in v2:
==============
* Rebase on 5.0-rc1
* Add patch to move bad block marker position info to a common place and
  rename/prepare existing flags
* improve/rename function nand_bbm_get_next_page() to use new flags
---
Frieder Schrempf (7):
  mtd: rawnand: Always store info about bad block markers in chip struct
  mtd: onenand: Store bad block marker position in chip struct
  mtd: nand: Cleanup flags and fields for bad block marker position
  mtd: nand: Make flags for bad block marker position more granular
  mtd: rawnand: Support bad block markers in first, second or last page
  mtd: rawnand: ESMT: Also use the last page for bad block markers
  mtd: rawnand: AMD: Also use the last page for bad block markers

 drivers/mtd/nand/onenand/onenand_base.c |  5 +-
 drivers/mtd/nand/onenand/onenand_bbt.c  |  3 --
 drivers/mtd/nand/raw/internals.h        |  1 +
 drivers/mtd/nand/raw/nand_amd.c         |  8 +++-
 drivers/mtd/nand/raw/nand_base.c        | 64 +++++++++++++++++--------
 drivers/mtd/nand/raw/nand_bbt.c         | 28 +++++------
 drivers/mtd/nand/raw/nand_esmt.c        |  9 +++-
 drivers/mtd/nand/raw/nand_hynix.c       |  4 +-
 drivers/mtd/nand/raw/nand_macronix.c    |  2 +-
 drivers/mtd/nand/raw/nand_micron.c      |  2 +-
 drivers/mtd/nand/raw/nand_samsung.c     |  4 +-
 drivers/mtd/nand/raw/nand_toshiba.c     |  2 +-
 drivers/mtd/nand/raw/sh_flctl.c         |  4 +-
 include/linux/mtd/bbm.h                 | 14 +-----
 include/linux/mtd/onenand.h             |  3 ++
 include/linux/mtd/rawnand.h             | 15 ++++++
 16 files changed, 104 insertions(+), 64 deletions(-)

-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 1/7] mtd: rawnand: Always store info about bad block markers in chip struct
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, Schrempf Frieder, linux-kernel

From: Frieder Schrempf <frieder.schrempf@kontron.de>

The information about where the manufacturer puts the bad block
markers inside the bad block and in the OOB data is stored in
different places. Let's move this information to nand_chip.options
and nand_chip.badblockpos.

As this chip-specific information is not directly related to the
bad block table (BBT), we also rename the flags to NAND_BBM_*.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/mtd/nand/raw/nand_amd.c      |  2 +-
 drivers/mtd/nand/raw/nand_base.c     | 12 ++++++------
 drivers/mtd/nand/raw/nand_bbt.c      |  4 ++--
 drivers/mtd/nand/raw/nand_esmt.c     |  2 +-
 drivers/mtd/nand/raw/nand_hynix.c    |  4 ++--
 drivers/mtd/nand/raw/nand_macronix.c |  2 +-
 drivers/mtd/nand/raw/nand_micron.c   |  2 +-
 drivers/mtd/nand/raw/nand_samsung.c  |  4 ++--
 drivers/mtd/nand/raw/nand_toshiba.c  |  2 +-
 drivers/mtd/nand/raw/sh_flctl.c      |  4 ++--
 include/linux/mtd/rawnand.h          | 14 ++++++++++++++
 11 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 890c5b43e03c..6e248bdcc797 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,7 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index cca4b24d2ffa..c6199cc68d2f 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -298,11 +298,11 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 	int page, page_end, res;
 	u8 bad;
 
-	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (chip->options & NAND_BBM_LASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1);
+	page_end = page + ((chip->options & NAND_BBM_SECONDPAGE) ? 2 : 1);
 
 	for (; page < page_end; page++) {
 		res = chip->ecc.read_oob(chip, page);
@@ -541,7 +541,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	ops.mode = MTD_OPS_PLACE_OOB;
 
 	/* Write to first/last page(s) if necessary */
-	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (chip->options & NAND_BBM_LASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 	do {
 		res = nand_do_write_oob(chip, ofs, &ops);
@@ -550,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 
 		i++;
 		ofs += mtd->writesize;
-	} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+	} while ((chip->options & NAND_BBM_SECONDPAGE) && i < 2);
 
 	return ret;
 }
@@ -4576,9 +4576,9 @@ static void nand_decode_bbm_options(struct nand_chip *chip)
 
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
-		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+		chip->badblockpos = NAND_BBM_POS_LARGE;
 	else
-		chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
+		chip->badblockpos = NAND_BBM_POS_SMALL;
 }
 
 static inline bool is_full_id_nand(struct nand_flash_dev *type)
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 1b722fe9213c..12e92e307346 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -466,7 +466,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if (bd->options & NAND_BBT_SCAN2NDPAGE)
+	if (this->options & NAND_BBM_SECONDPAGE)
 		numpages = 2;
 	else
 		numpages = 1;
@@ -487,7 +487,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		from = (loff_t)startblock << this->bbt_erase_shift;
 	}
 
-	if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (this->options & NAND_BBM_LASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * numpages);
 
 	for (i = startblock; i < numblocks; i++) {
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 96f039a83bc8..80d2d3a1b5f2 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,7 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 343f477362d1..2789bf3857c9 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -672,9 +672,9 @@ static int hynix_nand_init(struct nand_chip *chip)
 	int ret;
 
 	if (!nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	hynix = kzalloc(sizeof(*hynix), GFP_KERNEL);
 	if (!hynix)
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 47d8cda547cf..6db7ced4b96b 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -62,7 +62,7 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
 static int macronix_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	macronix_nand_fix_broken_get_timings(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index b85e1c13b79e..ea6b6e80d6f8 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -448,7 +448,7 @@ static int micron_nand_init(struct nand_chip *chip)
 		goto err_free_manuf_data;
 
 	if (mtd->writesize == 2048)
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	ondie = micron_supports_on_die_ecc(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index e46d4c492ad8..3be737139210 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -121,9 +121,9 @@ static int samsung_nand_init(struct nand_chip *chip)
 		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
 
 	if (!nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index d068163b64b3..222a66bf0aa6 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -147,7 +147,7 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |=  NAND_BBM_SECONDPAGE;
 
 	/* Check that chip is BENAND and ECC mode is on-die */
 	if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index cf6b1be1cf9c..2017b00fadd8 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -101,14 +101,12 @@ static const struct mtd_ooblayout_ops flctl_4secc_oob_largepage_ops = {
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static struct nand_bbt_descr flctl_4secc_smallpage = {
-	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 11,
 	.len = 1,
 	.pattern = scan_ff_pattern,
 };
 
 static struct nand_bbt_descr flctl_4secc_largepage = {
-	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 0,
 	.len = 2,
 	.pattern = scan_ff_pattern,
@@ -1178,6 +1176,8 @@ static int flctl_probe(struct platform_device *pdev)
 	if (pdata->flcmncr_val & SEL_16BIT)
 		nand->options |= NAND_BUSWIDTH_16;
 
+	nand->options |= NAND_BBM_SECONDPAGE;
+
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 33e240acdc6d..b31f023f8887 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -169,6 +169,20 @@ enum nand_ecc_algo {
 /* Macros to identify the above */
 #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
 
+/*
+ * There are different places where the manufacturer stores the factory bad
+ * block markers.
+ *
+ * Position within the block: Each of these pages needs to be checked for a
+ * bad block marking pattern.
+ */
+#define NAND_BBM_SECONDPAGE		0x02000000
+#define NAND_BBM_LASTPAGE		0x04000000
+
+/* Position within the OOB data of the page */
+#define NAND_BBM_POS_SMALL		5
+#define NAND_BBM_POS_LARGE		0
+
 /* Non chip related options */
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	0x00010000
-- 
2.17.1

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

* [PATCH v4 1/7] mtd: rawnand: Always store info about bad block markers in chip struct
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, linux-kernel, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

The information about where the manufacturer puts the bad block
markers inside the bad block and in the OOB data is stored in
different places. Let's move this information to nand_chip.options
and nand_chip.badblockpos.

As this chip-specific information is not directly related to the
bad block table (BBT), we also rename the flags to NAND_BBM_*.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/mtd/nand/raw/nand_amd.c      |  2 +-
 drivers/mtd/nand/raw/nand_base.c     | 12 ++++++------
 drivers/mtd/nand/raw/nand_bbt.c      |  4 ++--
 drivers/mtd/nand/raw/nand_esmt.c     |  2 +-
 drivers/mtd/nand/raw/nand_hynix.c    |  4 ++--
 drivers/mtd/nand/raw/nand_macronix.c |  2 +-
 drivers/mtd/nand/raw/nand_micron.c   |  2 +-
 drivers/mtd/nand/raw/nand_samsung.c  |  4 ++--
 drivers/mtd/nand/raw/nand_toshiba.c  |  2 +-
 drivers/mtd/nand/raw/sh_flctl.c      |  4 ++--
 include/linux/mtd/rawnand.h          | 14 ++++++++++++++
 11 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 890c5b43e03c..6e248bdcc797 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,7 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index cca4b24d2ffa..c6199cc68d2f 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -298,11 +298,11 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 	int page, page_end, res;
 	u8 bad;
 
-	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (chip->options & NAND_BBM_LASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1);
+	page_end = page + ((chip->options & NAND_BBM_SECONDPAGE) ? 2 : 1);
 
 	for (; page < page_end; page++) {
 		res = chip->ecc.read_oob(chip, page);
@@ -541,7 +541,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	ops.mode = MTD_OPS_PLACE_OOB;
 
 	/* Write to first/last page(s) if necessary */
-	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (chip->options & NAND_BBM_LASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 	do {
 		res = nand_do_write_oob(chip, ofs, &ops);
@@ -550,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 
 		i++;
 		ofs += mtd->writesize;
-	} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
+	} while ((chip->options & NAND_BBM_SECONDPAGE) && i < 2);
 
 	return ret;
 }
@@ -4576,9 +4576,9 @@ static void nand_decode_bbm_options(struct nand_chip *chip)
 
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
-		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+		chip->badblockpos = NAND_BBM_POS_LARGE;
 	else
-		chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
+		chip->badblockpos = NAND_BBM_POS_SMALL;
 }
 
 static inline bool is_full_id_nand(struct nand_flash_dev *type)
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 1b722fe9213c..12e92e307346 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -466,7 +466,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if (bd->options & NAND_BBT_SCAN2NDPAGE)
+	if (this->options & NAND_BBM_SECONDPAGE)
 		numpages = 2;
 	else
 		numpages = 1;
@@ -487,7 +487,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		from = (loff_t)startblock << this->bbt_erase_shift;
 	}
 
-	if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
+	if (this->options & NAND_BBM_LASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * numpages);
 
 	for (i = startblock; i < numblocks; i++) {
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 96f039a83bc8..80d2d3a1b5f2 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,7 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 343f477362d1..2789bf3857c9 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -672,9 +672,9 @@ static int hynix_nand_init(struct nand_chip *chip)
 	int ret;
 
 	if (!nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	hynix = kzalloc(sizeof(*hynix), GFP_KERNEL);
 	if (!hynix)
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 47d8cda547cf..6db7ced4b96b 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -62,7 +62,7 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
 static int macronix_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	macronix_nand_fix_broken_get_timings(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index b85e1c13b79e..ea6b6e80d6f8 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -448,7 +448,7 @@ static int micron_nand_init(struct nand_chip *chip)
 		goto err_free_manuf_data;
 
 	if (mtd->writesize == 2048)
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	ondie = micron_supports_on_die_ecc(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index e46d4c492ad8..3be737139210 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -121,9 +121,9 @@ static int samsung_nand_init(struct nand_chip *chip)
 		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
 
 	if (!nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index d068163b64b3..222a66bf0aa6 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -147,7 +147,7 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+		chip->options |=  NAND_BBM_SECONDPAGE;
 
 	/* Check that chip is BENAND and ECC mode is on-die */
 	if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index cf6b1be1cf9c..2017b00fadd8 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -101,14 +101,12 @@ static const struct mtd_ooblayout_ops flctl_4secc_oob_largepage_ops = {
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static struct nand_bbt_descr flctl_4secc_smallpage = {
-	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 11,
 	.len = 1,
 	.pattern = scan_ff_pattern,
 };
 
 static struct nand_bbt_descr flctl_4secc_largepage = {
-	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 0,
 	.len = 2,
 	.pattern = scan_ff_pattern,
@@ -1178,6 +1176,8 @@ static int flctl_probe(struct platform_device *pdev)
 	if (pdata->flcmncr_val & SEL_16BIT)
 		nand->options |= NAND_BUSWIDTH_16;
 
+	nand->options |= NAND_BBM_SECONDPAGE;
+
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 33e240acdc6d..b31f023f8887 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -169,6 +169,20 @@ enum nand_ecc_algo {
 /* Macros to identify the above */
 #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
 
+/*
+ * There are different places where the manufacturer stores the factory bad
+ * block markers.
+ *
+ * Position within the block: Each of these pages needs to be checked for a
+ * bad block marking pattern.
+ */
+#define NAND_BBM_SECONDPAGE		0x02000000
+#define NAND_BBM_LASTPAGE		0x04000000
+
+/* Position within the OOB data of the page */
+#define NAND_BBM_POS_SMALL		5
+#define NAND_BBM_POS_LARGE		0
+
 /* Non chip related options */
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	0x00010000
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, Kyungmin Park,
	David Woodhouse, Brian Norris, Marek Vasut
  Cc: linux-mtd, Schrempf Frieder, linux-kernel

From: Frieder Schrempf <frieder.schrempf@kontron.de>

The information about where the manufacturer puts the bad block
markers inside the bad block and in the OOB data is stored in
different places. Let's move this information to the chip struct,
as we did it for rawnand.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
 drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
 include/linux/mtd/onenand.h             | 3 +++
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
index 4ca4b194e7d7..f41d76248550 100644
--- a/drivers/mtd/nand/onenand/onenand_base.c
+++ b/drivers/mtd/nand/onenand/onenand_base.c
@@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
                 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
         /* We write two bytes, so we don't have to mess with 16-bit access */
-        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
+        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
 	/* FIXME : What to do when marking SLC block in partition
 	 * 	   with MLC erasesize? For now, it is not advisable to
 	 *	   create partitions containing both SLC and MLC regions.
@@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
 		this->unlock_all(mtd);
 
+	/* Set the bad block marker position */
+	this->badblockpos = ONENAND_BADBLOCK_POS;
+
 	ret = this->scan_bbt(mtd);
 	if ((!FLEXONENAND(this)) || ret)
 		return ret;
diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
index dde20487937d..57c31c81be18 100644
--- a/drivers/mtd/nand/onenand/onenand_bbt.c
+++ b/drivers/mtd/nand/onenand/onenand_bbt.c
@@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	if (!bbm->bbt)
 		return -ENOMEM;
 
-	/* Set the bad block position */
-	bbm->badblockpos = ONENAND_BADBLOCK_POS;
-
 	/* Set erase shift */
 	bbm->bbt_erase_shift = this->erase_shift;
 
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 0aaa98b219a4..e03aea7f7e61 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -94,6 +94,7 @@ struct onenand_chip {
 	unsigned int		technology;
 	unsigned int		density_mask;
 	unsigned int		options;
+	int			badblockpos;
 
 	unsigned int		erase_shift;
 	unsigned int		page_shift;
@@ -188,6 +189,8 @@ struct onenand_chip {
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
 
+#define ONENAND_BADBLOCK_POS		0
+
 /*
  * Options bits
  */
-- 
2.17.1

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

* [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, Kyungmin Park,
	David Woodhouse, Brian Norris, Marek Vasut
  Cc: linux-mtd, linux-kernel, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

The information about where the manufacturer puts the bad block
markers inside the bad block and in the OOB data is stored in
different places. Let's move this information to the chip struct,
as we did it for rawnand.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
 drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
 include/linux/mtd/onenand.h             | 3 +++
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
index 4ca4b194e7d7..f41d76248550 100644
--- a/drivers/mtd/nand/onenand/onenand_base.c
+++ b/drivers/mtd/nand/onenand/onenand_base.c
@@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
                 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
         /* We write two bytes, so we don't have to mess with 16-bit access */
-        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
+        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
 	/* FIXME : What to do when marking SLC block in partition
 	 * 	   with MLC erasesize? For now, it is not advisable to
 	 *	   create partitions containing both SLC and MLC regions.
@@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
 		this->unlock_all(mtd);
 
+	/* Set the bad block marker position */
+	this->badblockpos = ONENAND_BADBLOCK_POS;
+
 	ret = this->scan_bbt(mtd);
 	if ((!FLEXONENAND(this)) || ret)
 		return ret;
diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
index dde20487937d..57c31c81be18 100644
--- a/drivers/mtd/nand/onenand/onenand_bbt.c
+++ b/drivers/mtd/nand/onenand/onenand_bbt.c
@@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	if (!bbm->bbt)
 		return -ENOMEM;
 
-	/* Set the bad block position */
-	bbm->badblockpos = ONENAND_BADBLOCK_POS;
-
 	/* Set erase shift */
 	bbm->bbt_erase_shift = this->erase_shift;
 
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 0aaa98b219a4..e03aea7f7e61 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -94,6 +94,7 @@ struct onenand_chip {
 	unsigned int		technology;
 	unsigned int		density_mask;
 	unsigned int		options;
+	int			badblockpos;
 
 	unsigned int		erase_shift;
 	unsigned int		page_shift;
@@ -188,6 +189,8 @@ struct onenand_chip {
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
 
+#define ONENAND_BADBLOCK_POS		0
+
 /*
  * Options bits
  */
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 3/7] mtd: nand: Cleanup flags and fields for bad block marker position
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, Schrempf Frieder, linux-kernel

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Now that we have moved the information to the chip level, let's
remove all the unused flags and fields.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 include/linux/mtd/bbm.h | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 3102bd754d18..010bc5544c54 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -93,10 +93,7 @@ struct nand_bbt_descr {
 #define NAND_BBT_WRITE		0x00002000
 /* Read and write back block contents when writing bbt */
 #define NAND_BBT_SAVECONTENT	0x00004000
-/* Search good / bad pattern on the first and the second page */
-#define NAND_BBT_SCAN2NDPAGE	0x00008000
-/* Search good / bad pattern on the last page of the eraseblock */
-#define NAND_BBT_SCANLASTPAGE	0x00010000
+
 /*
  * Use a flash based bad block table. By default, OOB identifier is saved in
  * OOB area. This option is passed to the default bad block table function.
@@ -123,13 +120,6 @@ struct nand_bbt_descr {
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 
-/*
- * Constants for oob configuration
- */
-#define NAND_SMALL_BADBLOCK_POS		5
-#define NAND_LARGE_BADBLOCK_POS		0
-#define ONENAND_BADBLOCK_POS		0
-
 /*
  * Bad block scanning errors
  */
@@ -140,7 +130,6 @@ struct nand_bbt_descr {
 /**
  * struct bbm_info - [GENERIC] Bad Block Table data structure
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
- * @badblockpos:	[INTERN] position of the bad block marker in the oob area
  * @options:		options for this descriptor
  * @bbt:		[INTERN] bad block table pointer
  * @isbad_bbt:		function to determine if a block is bad
@@ -150,7 +139,6 @@ struct nand_bbt_descr {
  */
 struct bbm_info {
 	int bbt_erase_shift;
-	int badblockpos;
 	int options;
 
 	uint8_t *bbt;
-- 
2.17.1

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

* [PATCH v4 3/7] mtd: nand: Cleanup flags and fields for bad block marker position
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, linux-kernel, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Now that we have moved the information to the chip level, let's
remove all the unused flags and fields.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
 include/linux/mtd/bbm.h | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 3102bd754d18..010bc5544c54 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -93,10 +93,7 @@ struct nand_bbt_descr {
 #define NAND_BBT_WRITE		0x00002000
 /* Read and write back block contents when writing bbt */
 #define NAND_BBT_SAVECONTENT	0x00004000
-/* Search good / bad pattern on the first and the second page */
-#define NAND_BBT_SCAN2NDPAGE	0x00008000
-/* Search good / bad pattern on the last page of the eraseblock */
-#define NAND_BBT_SCANLASTPAGE	0x00010000
+
 /*
  * Use a flash based bad block table. By default, OOB identifier is saved in
  * OOB area. This option is passed to the default bad block table function.
@@ -123,13 +120,6 @@ struct nand_bbt_descr {
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 
-/*
- * Constants for oob configuration
- */
-#define NAND_SMALL_BADBLOCK_POS		5
-#define NAND_LARGE_BADBLOCK_POS		0
-#define ONENAND_BADBLOCK_POS		0
-
 /*
  * Bad block scanning errors
  */
@@ -140,7 +130,6 @@ struct nand_bbt_descr {
 /**
  * struct bbm_info - [GENERIC] Bad Block Table data structure
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
- * @badblockpos:	[INTERN] position of the bad block marker in the oob area
  * @options:		options for this descriptor
  * @bbt:		[INTERN] bad block table pointer
  * @isbad_bbt:		function to determine if a block is bad
@@ -150,7 +139,6 @@ struct nand_bbt_descr {
  */
 struct bbm_info {
 	int bbt_erase_shift;
-	int badblockpos;
 	int options;
 
 	uint8_t *bbt;
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 4/7] mtd: nand: Make flags for bad block marker position more granular
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, Schrempf Frieder, linux-kernel

From: Frieder Schrempf <frieder.schrempf@kontron.de>

To be able to check and set bad block markers in the first and
second page of a block independently of each other, we create
separate flags for both cases.

Previously NAND_BBM_SECONDPAGE meant, that both, the first and the
second page were used. With this patch NAND_BBM_FIRSTPAGE stands for
using the first page and NAND_BBM_SECONDPAGE for using the second
page.

This patch is only for preparation of subsequent changes and does
not implement the logic to actually handle both flags separately.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_amd.c      | 2 +-
 drivers/mtd/nand/raw/nand_base.c     | 6 ++++--
 drivers/mtd/nand/raw/nand_bbt.c      | 3 ++-
 drivers/mtd/nand/raw/nand_esmt.c     | 2 +-
 drivers/mtd/nand/raw/nand_hynix.c    | 2 +-
 drivers/mtd/nand/raw/nand_macronix.c | 2 +-
 drivers/mtd/nand/raw/nand_micron.c   | 2 +-
 drivers/mtd/nand/raw/nand_samsung.c  | 2 +-
 drivers/mtd/nand/raw/nand_toshiba.c  | 2 +-
 drivers/mtd/nand/raw/sh_flctl.c      | 2 +-
 include/linux/mtd/rawnand.h          | 1 +
 11 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 6e248bdcc797..6202cbf7ee8d 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,7 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index c6199cc68d2f..9ef7b86cdc42 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -302,7 +302,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + ((chip->options & NAND_BBM_SECONDPAGE) ? 2 : 1);
+	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
+			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
 
 	for (; page < page_end; page++) {
 		res = chip->ecc.read_oob(chip, page);
@@ -550,7 +551,8 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 
 		i++;
 		ofs += mtd->writesize;
-	} while ((chip->options & NAND_BBM_SECONDPAGE) && i < 2);
+	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
+		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 12e92e307346..7463afddc7ac 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -466,7 +466,8 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if (this->options & NAND_BBM_SECONDPAGE)
+	if ((this->options & NAND_BBM_FIRSTPAGE) &&
+	    (this->options & NAND_BBM_SECONDPAGE))
 		numpages = 2;
 	else
 		numpages = 1;
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 80d2d3a1b5f2..99a8092969a7 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,7 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 2789bf3857c9..e685d70c1618 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -674,7 +674,7 @@ static int hynix_nand_init(struct nand_chip *chip)
 	if (!nand_is_slc(chip))
 		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	hynix = kzalloc(sizeof(*hynix), GFP_KERNEL);
 	if (!hynix)
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 6db7ced4b96b..e287e71347c5 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -62,7 +62,7 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
 static int macronix_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	macronix_nand_fix_broken_get_timings(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index ea6b6e80d6f8..ca80e09783c7 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -448,7 +448,7 @@ static int micron_nand_init(struct nand_chip *chip)
 		goto err_free_manuf_data;
 
 	if (mtd->writesize == 2048)
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	ondie = micron_supports_on_die_ecc(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index 3be737139210..ace50522dd19 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -123,7 +123,7 @@ static int samsung_nand_init(struct nand_chip *chip)
 	if (!nand_is_slc(chip))
 		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 222a66bf0aa6..0031e6727193 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -147,7 +147,7 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |=  NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	/* Check that chip is BENAND and ECC mode is on-die */
 	if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index 2017b00fadd8..971d9afd55e5 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -1176,7 +1176,7 @@ static int flctl_probe(struct platform_device *pdev)
 	if (pdata->flcmncr_val & SEL_16BIT)
 		nand->options |= NAND_BUSWIDTH_16;
 
-	nand->options |= NAND_BBM_SECONDPAGE;
+	nand->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b31f023f8887..6fe784737e27 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -176,6 +176,7 @@ enum nand_ecc_algo {
  * Position within the block: Each of these pages needs to be checked for a
  * bad block marking pattern.
  */
+#define NAND_BBM_FIRSTPAGE		0x01000000
 #define NAND_BBM_SECONDPAGE		0x02000000
 #define NAND_BBM_LASTPAGE		0x04000000
 
-- 
2.17.1

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

* [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: linux-mtd, Schrempf Frieder, David Woodhouse, Brian Norris, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Currently supported bad block marker positions within the block are:
* in first page only
* in last page only
* in first or second page

Some ESMT NANDs are known to have been shipped by the manufacturer
with bad block markers in the first or last page, instead of the
first or second page.

Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
first, second *and* last page needs to be checked.

Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
combination.

To simplify the code, the logic to evaluate the flags is moved to a
a new function nand_bbm_get_next_page().

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/internals.h |  1 +
 drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
 drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
 3 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index fbf6ca015cd7..97ae67e009d5 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 
 /* Core functions */
 const struct nand_manufacturer *nand_get_manufacturer(u8 id);
+int nand_bbm_get_next_page(struct nand_chip *chip, int page);
 int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
 int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 		    int allowbbt);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9ef7b86cdc42..7bc20c1fe23c 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
 	spin_unlock(&chip->controller->lock);
 }
 
+/**
+ * nand_bbm_get_next_page - Get the next page for bad block markers
+ * @chip: NAND chip object
+ * @index: Current page, only pages beyond this will be considered
+ *
+ * Returns an integer that corresponds to the page offset within a block, for
+ * a page that is used to store bad block markers. If no more pages are
+ * available, -1 is returned.
+ */
+int nand_bbm_get_next_page(struct nand_chip *chip, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int last_page = ((mtd->erasesize - mtd->writesize) >>
+			 chip->page_shift) & chip->pagemask;
+
+	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
+		return 0;
+	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
+		return 1;
+	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
+		return last_page;
+
+	return -1;
+}
+
 /**
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
  * @chip: NAND chip object
@@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
  */
 static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	int page, page_end, res;
+	int page_offset;
+	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
 	u8 bad;
 
-	if (chip->options & NAND_BBM_LASTPAGE)
-		ofs += mtd->erasesize - mtd->writesize;
+	page_offset = nand_bbm_get_next_page(chip, -1);
 
-	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
-			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
-
-	for (; page < page_end; page++) {
-		res = chip->ecc.read_oob(chip, page);
+	while (page_offset != -1) {
+		res = chip->ecc.read_oob(chip, first_page + page_offset);
 		if (res < 0)
 			return res;
 
@@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 			res = hweight8(bad) < chip->badblockbits;
 		if (res)
 			return res;
+
+		page_offset = nand_bbm_get_next_page(chip, page_offset);
 	}
 
 	return 0;
@@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct mtd_oob_ops ops;
 	uint8_t buf[2] = { 0, 0 };
-	int ret = 0, res, i = 0;
+	int ret = 0, res, page_offset;
 
 	memset(&ops, 0, sizeof(ops));
 	ops.oobbuf = buf;
@@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	}
 	ops.mode = MTD_OPS_PLACE_OOB;
 
-	/* Write to first/last page(s) if necessary */
-	if (chip->options & NAND_BBM_LASTPAGE)
-		ofs += mtd->erasesize - mtd->writesize;
-	do {
-		res = nand_do_write_oob(chip, ofs, &ops);
+	page_offset = nand_bbm_get_next_page(chip, -1);
+
+	while (page_offset != -1) {
+		res = nand_do_write_oob(chip,
+					ofs + page_offset * mtd->writesize,
+					&ops);
+
 		if (!ret)
 			ret = res;
 
-		i++;
-		ofs += mtd->writesize;
-	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
-		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
+		page_offset = nand_bbm_get_next_page(chip, page_offset);
+	}
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 7463afddc7ac..09603c502931 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
 
 /* Scan a given block partially */
 static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
-			   loff_t offs, uint8_t *buf, int numpages)
+			   loff_t offs, uint8_t *buf)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
+
 	struct mtd_oob_ops ops;
-	int j, ret;
+	int ret, page_offset;
 
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = buf;
@@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
 	ops.datbuf = NULL;
 	ops.mode = MTD_OPS_PLACE_OOB;
 
-	for (j = 0; j < numpages; j++) {
+	page_offset = nand_bbm_get_next_page(this, -1);
+
+	while (page_offset != -1) {
 		/*
 		 * Read the full oob until read_oob is fixed to handle single
 		 * byte reads for 16 bit buswidth.
 		 */
-		ret = mtd_read_oob(mtd, offs, &ops);
+		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,
+				   &ops);
 		/* Ignore ECC errors when checking for BBM */
 		if (ret && !mtd_is_bitflip_or_eccerr(ret))
 			return ret;
@@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
 		if (check_short_pattern(buf, bd))
 			return 1;
 
-		offs += mtd->writesize;
+		page_offset = nand_bbm_get_next_page(this, page_offset);
 	}
+
 	return 0;
 }
 
@@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		      struct nand_bbt_descr *bd, int chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
-	int i, numblocks, numpages;
-	int startblock;
+	int i, numblocks, startblock;
 	loff_t from;
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if ((this->options & NAND_BBM_FIRSTPAGE) &&
-	    (this->options & NAND_BBM_SECONDPAGE))
-		numpages = 2;
-	else
-		numpages = 1;
-
 	if (chip == -1) {
 		numblocks = mtd->size >> this->bbt_erase_shift;
 		startblock = 0;
@@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		from = (loff_t)startblock << this->bbt_erase_shift;
 	}
 
-	if (this->options & NAND_BBM_LASTPAGE)
-		from += mtd->erasesize - (mtd->writesize * numpages);
-
 	for (i = startblock; i < numblocks; i++) {
 		int ret;
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
 
-		ret = scan_block_fast(this, bd, from, buf, numpages);
+		ret = scan_block_fast(this, bd, from, buf);
 		if (ret < 0)
 			return ret;
 
-- 
2.17.1

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

* [PATCH v4 6/7] mtd: rawnand: ESMT: Also use the last page for bad block markers
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: linux-mtd, Schrempf Frieder, David Woodhouse, Brian Norris, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

It is known that some ESMT SLC NANDs have been shipped
with the factory bad block markers in the first or last page
of the block, instead of the first or second page. To be on
the safe side, let's check all three locations.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_esmt.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 99a8092969a7..b37e0b5af5ae 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,14 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+		/*
+		 * It is known that some ESMT SLC NANDs have been shipped
+		 * with the factory bad block markers in the first or last page
+		 * of the block, instead of the first or second page. To be on
+		 * the safe side, let's check all three locations.
+		 */
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
+				 NAND_BBM_LASTPAGE;
 
 	return 0;
 }
-- 
2.17.1

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

* [PATCH v4 4/7] mtd: nand: Make flags for bad block marker position more granular
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, David Woodhouse,
	Brian Norris, Marek Vasut
  Cc: linux-mtd, linux-kernel, Schrempf Frieder

From: Frieder Schrempf <frieder.schrempf@kontron.de>

To be able to check and set bad block markers in the first and
second page of a block independently of each other, we create
separate flags for both cases.

Previously NAND_BBM_SECONDPAGE meant, that both, the first and the
second page were used. With this patch NAND_BBM_FIRSTPAGE stands for
using the first page and NAND_BBM_SECONDPAGE for using the second
page.

This patch is only for preparation of subsequent changes and does
not implement the logic to actually handle both flags separately.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_amd.c      | 2 +-
 drivers/mtd/nand/raw/nand_base.c     | 6 ++++--
 drivers/mtd/nand/raw/nand_bbt.c      | 3 ++-
 drivers/mtd/nand/raw/nand_esmt.c     | 2 +-
 drivers/mtd/nand/raw/nand_hynix.c    | 2 +-
 drivers/mtd/nand/raw/nand_macronix.c | 2 +-
 drivers/mtd/nand/raw/nand_micron.c   | 2 +-
 drivers/mtd/nand/raw/nand_samsung.c  | 2 +-
 drivers/mtd/nand/raw/nand_toshiba.c  | 2 +-
 drivers/mtd/nand/raw/sh_flctl.c      | 2 +-
 include/linux/mtd/rawnand.h          | 1 +
 11 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 6e248bdcc797..6202cbf7ee8d 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,7 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index c6199cc68d2f..9ef7b86cdc42 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -302,7 +302,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + ((chip->options & NAND_BBM_SECONDPAGE) ? 2 : 1);
+	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
+			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
 
 	for (; page < page_end; page++) {
 		res = chip->ecc.read_oob(chip, page);
@@ -550,7 +551,8 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 
 		i++;
 		ofs += mtd->writesize;
-	} while ((chip->options & NAND_BBM_SECONDPAGE) && i < 2);
+	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
+		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 12e92e307346..7463afddc7ac 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -466,7 +466,8 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if (this->options & NAND_BBM_SECONDPAGE)
+	if ((this->options & NAND_BBM_FIRSTPAGE) &&
+	    (this->options & NAND_BBM_SECONDPAGE))
 		numpages = 2;
 	else
 		numpages = 1;
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 80d2d3a1b5f2..99a8092969a7 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,7 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 2789bf3857c9..e685d70c1618 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -674,7 +674,7 @@ static int hynix_nand_init(struct nand_chip *chip)
 	if (!nand_is_slc(chip))
 		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	hynix = kzalloc(sizeof(*hynix), GFP_KERNEL);
 	if (!hynix)
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 6db7ced4b96b..e287e71347c5 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -62,7 +62,7 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
 static int macronix_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	macronix_nand_fix_broken_get_timings(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index ea6b6e80d6f8..ca80e09783c7 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -448,7 +448,7 @@ static int micron_nand_init(struct nand_chip *chip)
 		goto err_free_manuf_data;
 
 	if (mtd->writesize == 2048)
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	ondie = micron_supports_on_die_ecc(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index 3be737139210..ace50522dd19 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -123,7 +123,7 @@ static int samsung_nand_init(struct nand_chip *chip)
 	if (!nand_is_slc(chip))
 		chip->options |= NAND_BBM_LASTPAGE;
 	else
-		chip->options |= NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 222a66bf0aa6..0031e6727193 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -147,7 +147,7 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |=  NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	/* Check that chip is BENAND and ECC mode is on-die */
 	if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE &&
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index 2017b00fadd8..971d9afd55e5 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -1176,7 +1176,7 @@ static int flctl_probe(struct platform_device *pdev)
 	if (pdata->flcmncr_val & SEL_16BIT)
 		nand->options |= NAND_BUSWIDTH_16;
 
-	nand->options |= NAND_BBM_SECONDPAGE;
+	nand->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b31f023f8887..6fe784737e27 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -176,6 +176,7 @@ enum nand_ecc_algo {
  * Position within the block: Each of these pages needs to be checked for a
  * bad block marking pattern.
  */
+#define NAND_BBM_FIRSTPAGE		0x01000000
 #define NAND_BBM_SECONDPAGE		0x02000000
 #define NAND_BBM_LASTPAGE		0x04000000
 
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: David Woodhouse, Brian Norris, linux-mtd, Schrempf Frieder, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

Currently supported bad block marker positions within the block are:
* in first page only
* in last page only
* in first or second page

Some ESMT NANDs are known to have been shipped by the manufacturer
with bad block markers in the first or last page, instead of the
first or second page.

Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
first, second *and* last page needs to be checked.

Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
combination.

To simplify the code, the logic to evaluate the flags is moved to a
a new function nand_bbm_get_next_page().

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/internals.h |  1 +
 drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
 drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
 3 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index fbf6ca015cd7..97ae67e009d5 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 
 /* Core functions */
 const struct nand_manufacturer *nand_get_manufacturer(u8 id);
+int nand_bbm_get_next_page(struct nand_chip *chip, int page);
 int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
 int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 		    int allowbbt);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9ef7b86cdc42..7bc20c1fe23c 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
 	spin_unlock(&chip->controller->lock);
 }
 
+/**
+ * nand_bbm_get_next_page - Get the next page for bad block markers
+ * @chip: NAND chip object
+ * @index: Current page, only pages beyond this will be considered
+ *
+ * Returns an integer that corresponds to the page offset within a block, for
+ * a page that is used to store bad block markers. If no more pages are
+ * available, -1 is returned.
+ */
+int nand_bbm_get_next_page(struct nand_chip *chip, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int last_page = ((mtd->erasesize - mtd->writesize) >>
+			 chip->page_shift) & chip->pagemask;
+
+	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
+		return 0;
+	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
+		return 1;
+	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
+		return last_page;
+
+	return -1;
+}
+
 /**
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
  * @chip: NAND chip object
@@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
  */
 static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	int page, page_end, res;
+	int page_offset;
+	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
 	u8 bad;
 
-	if (chip->options & NAND_BBM_LASTPAGE)
-		ofs += mtd->erasesize - mtd->writesize;
+	page_offset = nand_bbm_get_next_page(chip, -1);
 
-	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
-			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
-
-	for (; page < page_end; page++) {
-		res = chip->ecc.read_oob(chip, page);
+	while (page_offset != -1) {
+		res = chip->ecc.read_oob(chip, first_page + page_offset);
 		if (res < 0)
 			return res;
 
@@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
 			res = hweight8(bad) < chip->badblockbits;
 		if (res)
 			return res;
+
+		page_offset = nand_bbm_get_next_page(chip, page_offset);
 	}
 
 	return 0;
@@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct mtd_oob_ops ops;
 	uint8_t buf[2] = { 0, 0 };
-	int ret = 0, res, i = 0;
+	int ret = 0, res, page_offset;
 
 	memset(&ops, 0, sizeof(ops));
 	ops.oobbuf = buf;
@@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
 	}
 	ops.mode = MTD_OPS_PLACE_OOB;
 
-	/* Write to first/last page(s) if necessary */
-	if (chip->options & NAND_BBM_LASTPAGE)
-		ofs += mtd->erasesize - mtd->writesize;
-	do {
-		res = nand_do_write_oob(chip, ofs, &ops);
+	page_offset = nand_bbm_get_next_page(chip, -1);
+
+	while (page_offset != -1) {
+		res = nand_do_write_oob(chip,
+					ofs + page_offset * mtd->writesize,
+					&ops);
+
 		if (!ret)
 			ret = res;
 
-		i++;
-		ofs += mtd->writesize;
-	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
-		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
+		page_offset = nand_bbm_get_next_page(chip, page_offset);
+	}
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 7463afddc7ac..09603c502931 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
 
 /* Scan a given block partially */
 static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
-			   loff_t offs, uint8_t *buf, int numpages)
+			   loff_t offs, uint8_t *buf)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
+
 	struct mtd_oob_ops ops;
-	int j, ret;
+	int ret, page_offset;
 
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = buf;
@@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
 	ops.datbuf = NULL;
 	ops.mode = MTD_OPS_PLACE_OOB;
 
-	for (j = 0; j < numpages; j++) {
+	page_offset = nand_bbm_get_next_page(this, -1);
+
+	while (page_offset != -1) {
 		/*
 		 * Read the full oob until read_oob is fixed to handle single
 		 * byte reads for 16 bit buswidth.
 		 */
-		ret = mtd_read_oob(mtd, offs, &ops);
+		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,
+				   &ops);
 		/* Ignore ECC errors when checking for BBM */
 		if (ret && !mtd_is_bitflip_or_eccerr(ret))
 			return ret;
@@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
 		if (check_short_pattern(buf, bd))
 			return 1;
 
-		offs += mtd->writesize;
+		page_offset = nand_bbm_get_next_page(this, page_offset);
 	}
+
 	return 0;
 }
 
@@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		      struct nand_bbt_descr *bd, int chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
-	int i, numblocks, numpages;
-	int startblock;
+	int i, numblocks, startblock;
 	loff_t from;
 
 	pr_info("Scanning device for bad blocks\n");
 
-	if ((this->options & NAND_BBM_FIRSTPAGE) &&
-	    (this->options & NAND_BBM_SECONDPAGE))
-		numpages = 2;
-	else
-		numpages = 1;
-
 	if (chip == -1) {
 		numblocks = mtd->size >> this->bbt_erase_shift;
 		startblock = 0;
@@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
 		from = (loff_t)startblock << this->bbt_erase_shift;
 	}
 
-	if (this->options & NAND_BBM_LASTPAGE)
-		from += mtd->erasesize - (mtd->writesize * numpages);
-
 	for (i = startblock; i < numblocks; i++) {
 		int ret;
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
 
-		ret = scan_block_fast(this, bd, from, buf, numpages);
+		ret = scan_block_fast(this, bd, from, buf);
 		if (ret < 0)
 			return ret;
 
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 6/7] mtd: rawnand: ESMT: Also use the last page for bad block markers
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: David Woodhouse, Brian Norris, linux-mtd, Schrempf Frieder, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

It is known that some ESMT SLC NANDs have been shipped
with the factory bad block markers in the first or last page
of the block, instead of the first or second page. To be on
the safe side, let's check all three locations.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_esmt.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 99a8092969a7..b37e0b5af5ae 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -36,7 +36,14 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
 static int esmt_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+		/*
+		 * It is known that some ESMT SLC NANDs have been shipped
+		 * with the factory bad block markers in the first or last page
+		 * of the block, instead of the first or second page. To be on
+		 * the safe side, let's check all three locations.
+		 */
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
+				 NAND_BBM_LASTPAGE;
 
 	return 0;
 }
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v4 7/7] mtd: rawnand: AMD: Also use the last page for bad block markers
  2019-02-18 10:42 ` Schrempf Frieder
@ 2019-02-18 10:42   ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: linux-mtd, Schrempf Frieder, David Woodhouse, Brian Norris, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

According to the datasheet of some Cypress SLC NANDs, the bad
block markers can be in the first, second or last page of a block.
So let's check all three locations.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_amd.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 6202cbf7ee8d..2ffcddff3e27 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,13 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+		/*
+		 * According to the datasheet of some Cypress SLC NANDs,
+		 * the bad block markers can be in the first, second or last
+		 * page of a block. So let's check all three locations.
+		 */
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
+				 NAND_BBM_LASTPAGE;
 
 	return 0;
 }
-- 
2.17.1

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

* [PATCH v4 7/7] mtd: rawnand: AMD: Also use the last page for bad block markers
@ 2019-02-18 10:42   ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-02-18 10:42 UTC (permalink / raw)
  To: bbrezillon, miquel.raynal, richard, linux-kernel
  Cc: David Woodhouse, Brian Norris, linux-mtd, Schrempf Frieder, Marek Vasut

From: Frieder Schrempf <frieder.schrempf@kontron.de>

According to the datasheet of some Cypress SLC NANDs, the bad
block markers can be in the first, second or last page of a block.
So let's check all three locations.

Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
---
 drivers/mtd/nand/raw/nand_amd.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 6202cbf7ee8d..2ffcddff3e27 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -40,7 +40,13 @@ static void amd_nand_decode_id(struct nand_chip *chip)
 static int amd_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
-		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+		/*
+		 * According to the datasheet of some Cypress SLC NANDs,
+		 * the bad block markers can be in the first, second or last
+		 * page of a block. So let's check all three locations.
+		 */
+		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
+				 NAND_BBM_LASTPAGE;
 
 	return 0;
 }
-- 
2.17.1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-03-04 10:58     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-03-04 10:58 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, Kyungmin Park, David Woodhouse,
	Brian Norris, Marek Vasut, linux-mtd, linux-kernel

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:41 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> The information about where the manufacturer puts the bad block
> markers inside the bad block and in the OOB data is stored in
> different places. Let's move this information to the chip struct,
> as we did it for rawnand.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> ---
>  drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
>  drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
>  include/linux/mtd/onenand.h             | 3 +++
>  3 files changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> index 4ca4b194e7d7..f41d76248550 100644
> --- a/drivers/mtd/nand/onenand/onenand_base.c
> +++ b/drivers/mtd/nand/onenand/onenand_base.c
> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>                  bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
>  
>          /* We write two bytes, so we don't have to mess with 16-bit access */
> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
>  	/* FIXME : What to do when marking SLC block in partition
>  	 * 	   with MLC erasesize? For now, it is not advisable to
>  	 *	   create partitions containing both SLC and MLC regions.
> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>  	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
>  		this->unlock_all(mtd);
>  
> +	/* Set the bad block marker position */
> +	this->badblockpos = ONENAND_BADBLOCK_POS;
> +
>  	ret = this->scan_bbt(mtd);
>  	if ((!FLEXONENAND(this)) || ret)
>  		return ret;
> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
> index dde20487937d..57c31c81be18 100644
> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>  	if (!bbm->bbt)
>  		return -ENOMEM;
>  
> -	/* Set the bad block position */
> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
> -
>  	/* Set erase shift */
>  	bbm->bbt_erase_shift = this->erase_shift;
>  
> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
> index 0aaa98b219a4..e03aea7f7e61 100644
> --- a/include/linux/mtd/onenand.h
> +++ b/include/linux/mtd/onenand.h
> @@ -94,6 +94,7 @@ struct onenand_chip {
>  	unsigned int		technology;
>  	unsigned int		density_mask;
>  	unsigned int		options;
> +	int			badblockpos;

Any reason not to unsign this field?

>  
>  	unsigned int		erase_shift;
>  	unsigned int		page_shift;
> @@ -188,6 +189,8 @@ struct onenand_chip {
>  /* Check byte access in OneNAND */
>  #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
>  
> +#define ONENAND_BADBLOCK_POS		0
> +
>  /*
>   * Options bits
>   */

Thanks,
Miquèl

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
@ 2019-03-04 10:58     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-03-04 10:58 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, Kyungmin Park,
	linux-mtd, Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:41 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> The information about where the manufacturer puts the bad block
> markers inside the bad block and in the OOB data is stored in
> different places. Let's move this information to the chip struct,
> as we did it for rawnand.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> ---
>  drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
>  drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
>  include/linux/mtd/onenand.h             | 3 +++
>  3 files changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> index 4ca4b194e7d7..f41d76248550 100644
> --- a/drivers/mtd/nand/onenand/onenand_base.c
> +++ b/drivers/mtd/nand/onenand/onenand_base.c
> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>                  bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
>  
>          /* We write two bytes, so we don't have to mess with 16-bit access */
> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
>  	/* FIXME : What to do when marking SLC block in partition
>  	 * 	   with MLC erasesize? For now, it is not advisable to
>  	 *	   create partitions containing both SLC and MLC regions.
> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>  	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
>  		this->unlock_all(mtd);
>  
> +	/* Set the bad block marker position */
> +	this->badblockpos = ONENAND_BADBLOCK_POS;
> +
>  	ret = this->scan_bbt(mtd);
>  	if ((!FLEXONENAND(this)) || ret)
>  		return ret;
> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
> index dde20487937d..57c31c81be18 100644
> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>  	if (!bbm->bbt)
>  		return -ENOMEM;
>  
> -	/* Set the bad block position */
> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
> -
>  	/* Set erase shift */
>  	bbm->bbt_erase_shift = this->erase_shift;
>  
> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
> index 0aaa98b219a4..e03aea7f7e61 100644
> --- a/include/linux/mtd/onenand.h
> +++ b/include/linux/mtd/onenand.h
> @@ -94,6 +94,7 @@ struct onenand_chip {
>  	unsigned int		technology;
>  	unsigned int		density_mask;
>  	unsigned int		options;
> +	int			badblockpos;

Any reason not to unsign this field?

>  
>  	unsigned int		erase_shift;
>  	unsigned int		page_shift;
> @@ -188,6 +189,8 @@ struct onenand_chip {
>  /* Check byte access in OneNAND */
>  #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
>  
> +#define ONENAND_BADBLOCK_POS		0
> +
>  /*
>   * Options bits
>   */

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-03-04 11:21     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-03-04 11:21 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, linux-mtd, David Woodhouse,
	Brian Norris, Marek Vasut

Hi Schrempf,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> Currently supported bad block marker positions within the block are:
> * in first page only
> * in last page only
> * in first or second page
> 
> Some ESMT NANDs are known to have been shipped by the manufacturer
> with bad block markers in the first or last page, instead of the
> first or second page.
> 
> Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
> first, second *and* last page needs to be checked.
> 
> Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
> NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
> combination.
> 
> To simplify the code, the logic to evaluate the flags is moved to a
> a new function nand_bbm_get_next_page().
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/internals.h |  1 +
>  drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
>  drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
>  3 files changed, 55 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index fbf6ca015cd7..97ae67e009d5 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
>  
>  /* Core functions */
>  const struct nand_manufacturer *nand_get_manufacturer(u8 id);
> +int nand_bbm_get_next_page(struct nand_chip *chip, int page);
>  int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
>  int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
>  		    int allowbbt);
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 9ef7b86cdc42..7bc20c1fe23c 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
>  	spin_unlock(&chip->controller->lock);
>  }
>  
> +/**
> + * nand_bbm_get_next_page - Get the next page for bad block markers
> + * @chip: NAND chip object
> + * @index: Current page, only pages beyond this will be considered

Why pages *beyond*? Can't you change the logic to use the page from
where to start searching? I am not sure such a change would be
clearer in the rest of the code but I don't like the tests against
"-1". Maybe you could just check negative values instead.

> + *
> + * Returns an integer that corresponds to the page offset within a block, for
> + * a page that is used to store bad block markers. If no more pages are
> + * available, -1 is returned.
> + */
> +int nand_bbm_get_next_page(struct nand_chip *chip, int page)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	int last_page = ((mtd->erasesize - mtd->writesize) >>
> +			 chip->page_shift) & chip->pagemask;
> +
> +	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
> +		return 0;
> +	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
> +		return 1;
> +	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
> +		return last_page;
> +
> +	return -1;

I would prefer a named value (like -EINVAL) and checks against a
negative value (not -1).

> +}
> +
>  /**
>   * nand_block_bad - [DEFAULT] Read bad block marker from the chip
>   * @chip: NAND chip object
> @@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
>   */
>  static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> -	int page, page_end, res;
> +	int page_offset;
> +	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;

Maybe:

        int first_page, page_offset;
        int res;
        u8 bad;

        first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
        page_offset = nand_bbm_get_next_page(chip, -1);

>  	u8 bad;
>  
> -	if (chip->options & NAND_BBM_LASTPAGE)
> -		ofs += mtd->erasesize - mtd->writesize;
> +	page_offset = nand_bbm_get_next_page(chip, -1);
>  
> -	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> -	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
> -			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
> -
> -	for (; page < page_end; page++) {
> -		res = chip->ecc.read_oob(chip, page);
> +	while (page_offset != -1) {
> +		res = chip->ecc.read_oob(chip, first_page + page_offset);
>  		if (res < 0)
>  			return res;
>  
> @@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>  			res = hweight8(bad) < chip->badblockbits;
>  		if (res)
>  			return res;
> +
> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>  	}
>  
>  	return 0;
> @@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct mtd_oob_ops ops;
>  	uint8_t buf[2] = { 0, 0 };
> -	int ret = 0, res, i = 0;
> +	int ret = 0, res, page_offset;
>  
>  	memset(&ops, 0, sizeof(ops));
>  	ops.oobbuf = buf;
> @@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>  	}
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
> -	/* Write to first/last page(s) if necessary */
> -	if (chip->options & NAND_BBM_LASTPAGE)
> -		ofs += mtd->erasesize - mtd->writesize;
> -	do {
> -		res = nand_do_write_oob(chip, ofs, &ops);
> +	page_offset = nand_bbm_get_next_page(chip, -1);
> +
> +	while (page_offset != -1) {
> +		res = nand_do_write_oob(chip,
> +					ofs + page_offset * mtd->writesize,
> +					&ops);
> +
>  		if (!ret)
>  			ret = res;
>  
> -		i++;
> -		ofs += mtd->writesize;
> -	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
> -		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
> +	}
>  
>  	return ret;
>  }
> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
> index 7463afddc7ac..09603c502931 100644
> --- a/drivers/mtd/nand/raw/nand_bbt.c
> +++ b/drivers/mtd/nand/raw/nand_bbt.c
> @@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
>  
>  /* Scan a given block partially */
>  static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
> -			   loff_t offs, uint8_t *buf, int numpages)
> +			   loff_t offs, uint8_t *buf)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> +
>  	struct mtd_oob_ops ops;
> -	int j, ret;
> +	int ret, page_offset;
>  
>  	ops.ooblen = mtd->oobsize;
>  	ops.oobbuf = buf;
> @@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>  	ops.datbuf = NULL;
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
> -	for (j = 0; j < numpages; j++) {
> +	page_offset = nand_bbm_get_next_page(this, -1);
> +
> +	while (page_offset != -1) {
>  		/*
>  		 * Read the full oob until read_oob is fixed to handle single
>  		 * byte reads for 16 bit buswidth.
>  		 */
> -		ret = mtd_read_oob(mtd, offs, &ops);
> +		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,

Can you add '(' & ')' please?

> +				   &ops);
>  		/* Ignore ECC errors when checking for BBM */
>  		if (ret && !mtd_is_bitflip_or_eccerr(ret))
>  			return ret;
> @@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>  		if (check_short_pattern(buf, bd))
>  			return 1;
>  
> -		offs += mtd->writesize;
> +		page_offset = nand_bbm_get_next_page(this, page_offset);
>  	}
> +
>  	return 0;
>  }
>  
> @@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>  		      struct nand_bbt_descr *bd, int chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> -	int i, numblocks, numpages;
> -	int startblock;
> +	int i, numblocks, startblock;
>  	loff_t from;
>  
>  	pr_info("Scanning device for bad blocks\n");
>  
> -	if ((this->options & NAND_BBM_FIRSTPAGE) &&
> -	    (this->options & NAND_BBM_SECONDPAGE))
> -		numpages = 2;
> -	else
> -		numpages = 1;
> -
>  	if (chip == -1) {
>  		numblocks = mtd->size >> this->bbt_erase_shift;
>  		startblock = 0;
> @@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>  		from = (loff_t)startblock << this->bbt_erase_shift;
>  	}
>  
> -	if (this->options & NAND_BBM_LASTPAGE)
> -		from += mtd->erasesize - (mtd->writesize * numpages);
> -
>  	for (i = startblock; i < numblocks; i++) {
>  		int ret;
>  
>  		BUG_ON(bd->options & NAND_BBT_NO_OOB);
>  
> -		ret = scan_block_fast(this, bd, from, buf, numpages);
> +		ret = scan_block_fast(this, bd, from, buf);
>  		if (ret < 0)
>  			return ret;
>  




Thanks,
Miquèl

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

* Re: [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page
@ 2019-03-04 11:21     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-03-04 11:21 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Schrempf,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> Currently supported bad block marker positions within the block are:
> * in first page only
> * in last page only
> * in first or second page
> 
> Some ESMT NANDs are known to have been shipped by the manufacturer
> with bad block markers in the first or last page, instead of the
> first or second page.
> 
> Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
> first, second *and* last page needs to be checked.
> 
> Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
> NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
> combination.
> 
> To simplify the code, the logic to evaluate the flags is moved to a
> a new function nand_bbm_get_next_page().
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/internals.h |  1 +
>  drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
>  drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
>  3 files changed, 55 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index fbf6ca015cd7..97ae67e009d5 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
>  
>  /* Core functions */
>  const struct nand_manufacturer *nand_get_manufacturer(u8 id);
> +int nand_bbm_get_next_page(struct nand_chip *chip, int page);
>  int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
>  int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
>  		    int allowbbt);
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 9ef7b86cdc42..7bc20c1fe23c 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
>  	spin_unlock(&chip->controller->lock);
>  }
>  
> +/**
> + * nand_bbm_get_next_page - Get the next page for bad block markers
> + * @chip: NAND chip object
> + * @index: Current page, only pages beyond this will be considered

Why pages *beyond*? Can't you change the logic to use the page from
where to start searching? I am not sure such a change would be
clearer in the rest of the code but I don't like the tests against
"-1". Maybe you could just check negative values instead.

> + *
> + * Returns an integer that corresponds to the page offset within a block, for
> + * a page that is used to store bad block markers. If no more pages are
> + * available, -1 is returned.
> + */
> +int nand_bbm_get_next_page(struct nand_chip *chip, int page)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	int last_page = ((mtd->erasesize - mtd->writesize) >>
> +			 chip->page_shift) & chip->pagemask;
> +
> +	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
> +		return 0;
> +	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
> +		return 1;
> +	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
> +		return last_page;
> +
> +	return -1;

I would prefer a named value (like -EINVAL) and checks against a
negative value (not -1).

> +}
> +
>  /**
>   * nand_block_bad - [DEFAULT] Read bad block marker from the chip
>   * @chip: NAND chip object
> @@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
>   */
>  static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> -	int page, page_end, res;
> +	int page_offset;
> +	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;

Maybe:

        int first_page, page_offset;
        int res;
        u8 bad;

        first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
        page_offset = nand_bbm_get_next_page(chip, -1);

>  	u8 bad;
>  
> -	if (chip->options & NAND_BBM_LASTPAGE)
> -		ofs += mtd->erasesize - mtd->writesize;
> +	page_offset = nand_bbm_get_next_page(chip, -1);
>  
> -	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> -	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
> -			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
> -
> -	for (; page < page_end; page++) {
> -		res = chip->ecc.read_oob(chip, page);
> +	while (page_offset != -1) {
> +		res = chip->ecc.read_oob(chip, first_page + page_offset);
>  		if (res < 0)
>  			return res;
>  
> @@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>  			res = hweight8(bad) < chip->badblockbits;
>  		if (res)
>  			return res;
> +
> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>  	}
>  
>  	return 0;
> @@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct mtd_oob_ops ops;
>  	uint8_t buf[2] = { 0, 0 };
> -	int ret = 0, res, i = 0;
> +	int ret = 0, res, page_offset;
>  
>  	memset(&ops, 0, sizeof(ops));
>  	ops.oobbuf = buf;
> @@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>  	}
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
> -	/* Write to first/last page(s) if necessary */
> -	if (chip->options & NAND_BBM_LASTPAGE)
> -		ofs += mtd->erasesize - mtd->writesize;
> -	do {
> -		res = nand_do_write_oob(chip, ofs, &ops);
> +	page_offset = nand_bbm_get_next_page(chip, -1);
> +
> +	while (page_offset != -1) {
> +		res = nand_do_write_oob(chip,
> +					ofs + page_offset * mtd->writesize,
> +					&ops);
> +
>  		if (!ret)
>  			ret = res;
>  
> -		i++;
> -		ofs += mtd->writesize;
> -	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
> -		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
> +	}
>  
>  	return ret;
>  }
> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
> index 7463afddc7ac..09603c502931 100644
> --- a/drivers/mtd/nand/raw/nand_bbt.c
> +++ b/drivers/mtd/nand/raw/nand_bbt.c
> @@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
>  
>  /* Scan a given block partially */
>  static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
> -			   loff_t offs, uint8_t *buf, int numpages)
> +			   loff_t offs, uint8_t *buf)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> +
>  	struct mtd_oob_ops ops;
> -	int j, ret;
> +	int ret, page_offset;
>  
>  	ops.ooblen = mtd->oobsize;
>  	ops.oobbuf = buf;
> @@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>  	ops.datbuf = NULL;
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
> -	for (j = 0; j < numpages; j++) {
> +	page_offset = nand_bbm_get_next_page(this, -1);
> +
> +	while (page_offset != -1) {
>  		/*
>  		 * Read the full oob until read_oob is fixed to handle single
>  		 * byte reads for 16 bit buswidth.
>  		 */
> -		ret = mtd_read_oob(mtd, offs, &ops);
> +		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,

Can you add '(' & ')' please?

> +				   &ops);
>  		/* Ignore ECC errors when checking for BBM */
>  		if (ret && !mtd_is_bitflip_or_eccerr(ret))
>  			return ret;
> @@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>  		if (check_short_pattern(buf, bd))
>  			return 1;
>  
> -		offs += mtd->writesize;
> +		page_offset = nand_bbm_get_next_page(this, page_offset);
>  	}
> +
>  	return 0;
>  }
>  
> @@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>  		      struct nand_bbt_descr *bd, int chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> -	int i, numblocks, numpages;
> -	int startblock;
> +	int i, numblocks, startblock;
>  	loff_t from;
>  
>  	pr_info("Scanning device for bad blocks\n");
>  
> -	if ((this->options & NAND_BBM_FIRSTPAGE) &&
> -	    (this->options & NAND_BBM_SECONDPAGE))
> -		numpages = 2;
> -	else
> -		numpages = 1;
> -
>  	if (chip == -1) {
>  		numblocks = mtd->size >> this->bbt_erase_shift;
>  		startblock = 0;
> @@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>  		from = (loff_t)startblock << this->bbt_erase_shift;
>  	}
>  
> -	if (this->options & NAND_BBM_LASTPAGE)
> -		from += mtd->erasesize - (mtd->writesize * numpages);
> -
>  	for (i = startblock; i < numblocks; i++) {
>  		int ret;
>  
>  		BUG_ON(bd->options & NAND_BBT_NO_OOB);
>  
> -		ret = scan_block_fast(this, bd, from, buf, numpages);
> +		ret = scan_block_fast(this, bd, from, buf);
>  		if (ret < 0)
>  			return ret;
>  




Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
  2019-03-04 10:58     ` Miquel Raynal
@ 2019-03-21  8:47       ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-03-21  8:47 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: bbrezillon, richard, Kyungmin Park, David Woodhouse,
	Brian Norris, Marek Vasut, linux-mtd, linux-kernel

On 04.03.19 11:58, Miquel Raynal wrote:
> Hi Frieder,
> 
> Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> 2019 10:42:41 +0000:
> 
>> From: Frieder Schrempf <frieder.schrempf@kontron.de>
>>
>> The information about where the manufacturer puts the bad block
>> markers inside the bad block and in the OOB data is stored in
>> different places. Let's move this information to the chip struct,
>> as we did it for rawnand.
>>
>> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
>> ---
>>   drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
>>   drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
>>   include/linux/mtd/onenand.h             | 3 +++
>>   3 files changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
>> index 4ca4b194e7d7..f41d76248550 100644
>> --- a/drivers/mtd/nand/onenand/onenand_base.c
>> +++ b/drivers/mtd/nand/onenand/onenand_base.c
>> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>>                   bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
>>   
>>           /* We write two bytes, so we don't have to mess with 16-bit access */
>> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
>> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
>>   	/* FIXME : What to do when marking SLC block in partition
>>   	 * 	   with MLC erasesize? For now, it is not advisable to
>>   	 *	   create partitions containing both SLC and MLC regions.
>> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>>   	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
>>   		this->unlock_all(mtd);
>>   
>> +	/* Set the bad block marker position */
>> +	this->badblockpos = ONENAND_BADBLOCK_POS;
>> +
>>   	ret = this->scan_bbt(mtd);
>>   	if ((!FLEXONENAND(this)) || ret)
>>   		return ret;
>> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
>> index dde20487937d..57c31c81be18 100644
>> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
>> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
>> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>>   	if (!bbm->bbt)
>>   		return -ENOMEM;
>>   
>> -	/* Set the bad block position */
>> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
>> -
>>   	/* Set erase shift */
>>   	bbm->bbt_erase_shift = this->erase_shift;
>>   
>> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
>> index 0aaa98b219a4..e03aea7f7e61 100644
>> --- a/include/linux/mtd/onenand.h
>> +++ b/include/linux/mtd/onenand.h
>> @@ -94,6 +94,7 @@ struct onenand_chip {
>>   	unsigned int		technology;
>>   	unsigned int		density_mask;
>>   	unsigned int		options;
>> +	int			badblockpos;
> 
> Any reason not to unsign this field?

It was signed so far, but you're right that it makes more sense to 
unsign it.

> 
>>   
>>   	unsigned int		erase_shift;
>>   	unsigned int		page_shift;
>> @@ -188,6 +189,8 @@ struct onenand_chip {
>>   /* Check byte access in OneNAND */
>>   #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
>>   
>> +#define ONENAND_BADBLOCK_POS		0
>> +
>>   /*
>>    * Options bits
>>    */
> 
> Thanks,
> Miquèl
> 

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
@ 2019-03-21  8:47       ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-03-21  8:47 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, Kyungmin Park,
	linux-mtd, Brian Norris, David Woodhouse

On 04.03.19 11:58, Miquel Raynal wrote:
> Hi Frieder,
> 
> Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> 2019 10:42:41 +0000:
> 
>> From: Frieder Schrempf <frieder.schrempf@kontron.de>
>>
>> The information about where the manufacturer puts the bad block
>> markers inside the bad block and in the OOB data is stored in
>> different places. Let's move this information to the chip struct,
>> as we did it for rawnand.
>>
>> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
>> ---
>>   drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
>>   drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
>>   include/linux/mtd/onenand.h             | 3 +++
>>   3 files changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
>> index 4ca4b194e7d7..f41d76248550 100644
>> --- a/drivers/mtd/nand/onenand/onenand_base.c
>> +++ b/drivers/mtd/nand/onenand/onenand_base.c
>> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>>                   bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
>>   
>>           /* We write two bytes, so we don't have to mess with 16-bit access */
>> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
>> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
>>   	/* FIXME : What to do when marking SLC block in partition
>>   	 * 	   with MLC erasesize? For now, it is not advisable to
>>   	 *	   create partitions containing both SLC and MLC regions.
>> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>>   	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
>>   		this->unlock_all(mtd);
>>   
>> +	/* Set the bad block marker position */
>> +	this->badblockpos = ONENAND_BADBLOCK_POS;
>> +
>>   	ret = this->scan_bbt(mtd);
>>   	if ((!FLEXONENAND(this)) || ret)
>>   		return ret;
>> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
>> index dde20487937d..57c31c81be18 100644
>> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
>> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
>> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>>   	if (!bbm->bbt)
>>   		return -ENOMEM;
>>   
>> -	/* Set the bad block position */
>> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
>> -
>>   	/* Set erase shift */
>>   	bbm->bbt_erase_shift = this->erase_shift;
>>   
>> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
>> index 0aaa98b219a4..e03aea7f7e61 100644
>> --- a/include/linux/mtd/onenand.h
>> +++ b/include/linux/mtd/onenand.h
>> @@ -94,6 +94,7 @@ struct onenand_chip {
>>   	unsigned int		technology;
>>   	unsigned int		density_mask;
>>   	unsigned int		options;
>> +	int			badblockpos;
> 
> Any reason not to unsign this field?

It was signed so far, but you're right that it makes more sense to 
unsign it.

> 
>>   
>>   	unsigned int		erase_shift;
>>   	unsigned int		page_shift;
>> @@ -188,6 +189,8 @@ struct onenand_chip {
>>   /* Check byte access in OneNAND */
>>   #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
>>   
>> +#define ONENAND_BADBLOCK_POS		0
>> +
>>   /*
>>    * Options bits
>>    */
> 
> Thanks,
> Miquèl
> 
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page
  2019-03-04 11:21     ` Miquel Raynal
@ 2019-03-21  9:04       ` Schrempf Frieder
  -1 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-03-21  9:04 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: bbrezillon, richard, linux-kernel, linux-mtd, David Woodhouse,
	Brian Norris, Marek Vasut

On 04.03.19 12:21, Miquel Raynal wrote:
> Hi Schrempf,
> 
> Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> 2019 10:42:45 +0000:
> 
>> From: Frieder Schrempf <frieder.schrempf@kontron.de>
>>
>> Currently supported bad block marker positions within the block are:
>> * in first page only
>> * in last page only
>> * in first or second page
>>
>> Some ESMT NANDs are known to have been shipped by the manufacturer
>> with bad block markers in the first or last page, instead of the
>> first or second page.
>>
>> Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
>> first, second *and* last page needs to be checked.
>>
>> Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
>> NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
>> combination.
>>
>> To simplify the code, the logic to evaluate the flags is moved to a
>> a new function nand_bbm_get_next_page().
>>
>> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
>> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
>> ---
>>   drivers/mtd/nand/raw/internals.h |  1 +
>>   drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
>>   drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
>>   3 files changed, 55 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
>> index fbf6ca015cd7..97ae67e009d5 100644
>> --- a/drivers/mtd/nand/raw/internals.h
>> +++ b/drivers/mtd/nand/raw/internals.h
>> @@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
>>   
>>   /* Core functions */
>>   const struct nand_manufacturer *nand_get_manufacturer(u8 id);
>> +int nand_bbm_get_next_page(struct nand_chip *chip, int page);
>>   int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
>>   int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
>>   		    int allowbbt);
>> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
>> index 9ef7b86cdc42..7bc20c1fe23c 100644
>> --- a/drivers/mtd/nand/raw/nand_base.c
>> +++ b/drivers/mtd/nand/raw/nand_base.c
>> @@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
>>   	spin_unlock(&chip->controller->lock);
>>   }
>>   
>> +/**
>> + * nand_bbm_get_next_page - Get the next page for bad block markers
>> + * @chip: NAND chip object
>> + * @index: Current page, only pages beyond this will be considered
> 
> Why pages *beyond*? Can't you change the logic to use the page from
> where to start searching? I am not sure such a change would be
> clearer in the rest of the code but I don't like the tests against
> "-1". Maybe you could just check negative values instead.

I guess I can change to use the page from where to start searching as a 
parameter. If that's what you mean (inclusive instead of exclusive)? 
Then the initial call would look like "nand_bbm_get_next_page(chip, 0)" 
instead of "nand_bbm_get_next_page(chip, -1)" which seems a bit clearer.

>> + *
>> + * Returns an integer that corresponds to the page offset within a block, for
>> + * a page that is used to store bad block markers. If no more pages are
>> + * available, -1 is returned.
>> + */
>> +int nand_bbm_get_next_page(struct nand_chip *chip, int page)
>> +{
>> +	struct mtd_info *mtd = nand_to_mtd(chip);
>> +	int last_page = ((mtd->erasesize - mtd->writesize) >>
>> +			 chip->page_shift) & chip->pagemask;
>> +
>> +	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
>> +		return 0;
>> +	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
>> +		return 1;
>> +	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
>> +		return last_page;
>> +
>> +	return -1;
> 
> I would prefer a named value (like -EINVAL) and checks against a
> negative value (not -1).

Right, makes sense.

>> +}
>> +
>>   /**
>>    * nand_block_bad - [DEFAULT] Read bad block marker from the chip
>>    * @chip: NAND chip object
>> @@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
>>    */
>>   static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>>   {
>> -	struct mtd_info *mtd = nand_to_mtd(chip);
>> -	int page, page_end, res;
>> +	int page_offset;
>> +	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> 
> Maybe:
> 
>          int first_page, page_offset;
>          int res;
>          u8 bad;
> 
>          first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
>          page_offset = nand_bbm_get_next_page(chip, -1);

Looks better.

>>   	u8 bad;
>>   
>> -	if (chip->options & NAND_BBM_LASTPAGE)
>> -		ofs += mtd->erasesize - mtd->writesize;
>> +	page_offset = nand_bbm_get_next_page(chip, -1);
>>   
>> -	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
>> -	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
>> -			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
>> -
>> -	for (; page < page_end; page++) {
>> -		res = chip->ecc.read_oob(chip, page);
>> +	while (page_offset != -1) {
>> +		res = chip->ecc.read_oob(chip, first_page + page_offset);
>>   		if (res < 0)
>>   			return res;
>>   
>> @@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>>   			res = hweight8(bad) < chip->badblockbits;
>>   		if (res)
>>   			return res;
>> +
>> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>>   	}
>>   
>>   	return 0;
>> @@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>>   	struct mtd_info *mtd = nand_to_mtd(chip);
>>   	struct mtd_oob_ops ops;
>>   	uint8_t buf[2] = { 0, 0 };
>> -	int ret = 0, res, i = 0;
>> +	int ret = 0, res, page_offset;
>>   
>>   	memset(&ops, 0, sizeof(ops));
>>   	ops.oobbuf = buf;
>> @@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>>   	}
>>   	ops.mode = MTD_OPS_PLACE_OOB;
>>   
>> -	/* Write to first/last page(s) if necessary */
>> -	if (chip->options & NAND_BBM_LASTPAGE)
>> -		ofs += mtd->erasesize - mtd->writesize;
>> -	do {
>> -		res = nand_do_write_oob(chip, ofs, &ops);
>> +	page_offset = nand_bbm_get_next_page(chip, -1);
>> +
>> +	while (page_offset != -1) {
>> +		res = nand_do_write_oob(chip,
>> +					ofs + page_offset * mtd->writesize,
>> +					&ops);
>> +
>>   		if (!ret)
>>   			ret = res;
>>   
>> -		i++;
>> -		ofs += mtd->writesize;
>> -	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
>> -		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
>> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>> +	}
>>   
>>   	return ret;
>>   }
>> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
>> index 7463afddc7ac..09603c502931 100644
>> --- a/drivers/mtd/nand/raw/nand_bbt.c
>> +++ b/drivers/mtd/nand/raw/nand_bbt.c
>> @@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
>>   
>>   /* Scan a given block partially */
>>   static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>> -			   loff_t offs, uint8_t *buf, int numpages)
>> +			   loff_t offs, uint8_t *buf)
>>   {
>>   	struct mtd_info *mtd = nand_to_mtd(this);
>> +
>>   	struct mtd_oob_ops ops;
>> -	int j, ret;
>> +	int ret, page_offset;
>>   
>>   	ops.ooblen = mtd->oobsize;
>>   	ops.oobbuf = buf;
>> @@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>>   	ops.datbuf = NULL;
>>   	ops.mode = MTD_OPS_PLACE_OOB;
>>   
>> -	for (j = 0; j < numpages; j++) {
>> +	page_offset = nand_bbm_get_next_page(this, -1);
>> +
>> +	while (page_offset != -1) {
>>   		/*
>>   		 * Read the full oob until read_oob is fixed to handle single
>>   		 * byte reads for 16 bit buswidth.
>>   		 */
>> -		ret = mtd_read_oob(mtd, offs, &ops);
>> +		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,
> 
> Can you add '(' & ')' please?

Sure

>> +				   &ops);
>>   		/* Ignore ECC errors when checking for BBM */
>>   		if (ret && !mtd_is_bitflip_or_eccerr(ret))
>>   			return ret;
>> @@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>>   		if (check_short_pattern(buf, bd))
>>   			return 1;
>>   
>> -		offs += mtd->writesize;
>> +		page_offset = nand_bbm_get_next_page(this, page_offset);
>>   	}
>> +
>>   	return 0;
>>   }
>>   
>> @@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>>   		      struct nand_bbt_descr *bd, int chip)
>>   {
>>   	struct mtd_info *mtd = nand_to_mtd(this);
>> -	int i, numblocks, numpages;
>> -	int startblock;
>> +	int i, numblocks, startblock;
>>   	loff_t from;
>>   
>>   	pr_info("Scanning device for bad blocks\n");
>>   
>> -	if ((this->options & NAND_BBM_FIRSTPAGE) &&
>> -	    (this->options & NAND_BBM_SECONDPAGE))
>> -		numpages = 2;
>> -	else
>> -		numpages = 1;
>> -
>>   	if (chip == -1) {
>>   		numblocks = mtd->size >> this->bbt_erase_shift;
>>   		startblock = 0;
>> @@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>>   		from = (loff_t)startblock << this->bbt_erase_shift;
>>   	}
>>   
>> -	if (this->options & NAND_BBM_LASTPAGE)
>> -		from += mtd->erasesize - (mtd->writesize * numpages);
>> -
>>   	for (i = startblock; i < numblocks; i++) {
>>   		int ret;
>>   
>>   		BUG_ON(bd->options & NAND_BBT_NO_OOB);
>>   
>> -		ret = scan_block_fast(this, bd, from, buf, numpages);
>> +		ret = scan_block_fast(this, bd, from, buf);
>>   		if (ret < 0)
>>   			return ret;
>>   
> 
> 
> 
> 
> Thanks,
> Miquèl
> 

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

* Re: [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first,  second or last page
@ 2019-03-21  9:04       ` Schrempf Frieder
  0 siblings, 0 replies; 36+ messages in thread
From: Schrempf Frieder @ 2019-03-21  9:04 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

On 04.03.19 12:21, Miquel Raynal wrote:
> Hi Schrempf,
> 
> Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> 2019 10:42:45 +0000:
> 
>> From: Frieder Schrempf <frieder.schrempf@kontron.de>
>>
>> Currently supported bad block marker positions within the block are:
>> * in first page only
>> * in last page only
>> * in first or second page
>>
>> Some ESMT NANDs are known to have been shipped by the manufacturer
>> with bad block markers in the first or last page, instead of the
>> first or second page.
>>
>> Also the datasheets for Cypress/Spansion/AMD NANDs claim that the
>> first, second *and* last page needs to be checked.
>>
>> Therefore we make it possible to set NAND_BBM_FIRSTPAGE,
>> NAND_BBM_SECONDPAGE and NAND_BBM_LASTPAGE independently in any
>> combination.
>>
>> To simplify the code, the logic to evaluate the flags is moved to a
>> a new function nand_bbm_get_next_page().
>>
>> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
>> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
>> ---
>>   drivers/mtd/nand/raw/internals.h |  1 +
>>   drivers/mtd/nand/raw/nand_base.c | 62 ++++++++++++++++++++++++-----------
>>   drivers/mtd/nand/raw/nand_bbt.c  | 29 +++++++---------
>>   3 files changed, 55 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
>> index fbf6ca015cd7..97ae67e009d5 100644
>> --- a/drivers/mtd/nand/raw/internals.h
>> +++ b/drivers/mtd/nand/raw/internals.h
>> @@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
>>   
>>   /* Core functions */
>>   const struct nand_manufacturer *nand_get_manufacturer(u8 id);
>> +int nand_bbm_get_next_page(struct nand_chip *chip, int page);
>>   int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
>>   int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
>>   		    int allowbbt);
>> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
>> index 9ef7b86cdc42..7bc20c1fe23c 100644
>> --- a/drivers/mtd/nand/raw/nand_base.c
>> +++ b/drivers/mtd/nand/raw/nand_base.c
>> @@ -285,6 +285,31 @@ static void nand_release_device(struct nand_chip *chip)
>>   	spin_unlock(&chip->controller->lock);
>>   }
>>   
>> +/**
>> + * nand_bbm_get_next_page - Get the next page for bad block markers
>> + * @chip: NAND chip object
>> + * @index: Current page, only pages beyond this will be considered
> 
> Why pages *beyond*? Can't you change the logic to use the page from
> where to start searching? I am not sure such a change would be
> clearer in the rest of the code but I don't like the tests against
> "-1". Maybe you could just check negative values instead.

I guess I can change to use the page from where to start searching as a 
parameter. If that's what you mean (inclusive instead of exclusive)? 
Then the initial call would look like "nand_bbm_get_next_page(chip, 0)" 
instead of "nand_bbm_get_next_page(chip, -1)" which seems a bit clearer.

>> + *
>> + * Returns an integer that corresponds to the page offset within a block, for
>> + * a page that is used to store bad block markers. If no more pages are
>> + * available, -1 is returned.
>> + */
>> +int nand_bbm_get_next_page(struct nand_chip *chip, int page)
>> +{
>> +	struct mtd_info *mtd = nand_to_mtd(chip);
>> +	int last_page = ((mtd->erasesize - mtd->writesize) >>
>> +			 chip->page_shift) & chip->pagemask;
>> +
>> +	if (page < 0 && chip->options & NAND_BBM_FIRSTPAGE)
>> +		return 0;
>> +	else if (page < 1 && chip->options & NAND_BBM_SECONDPAGE)
>> +		return 1;
>> +	else if (page < last_page && chip->options & NAND_BBM_LASTPAGE)
>> +		return last_page;
>> +
>> +	return -1;
> 
> I would prefer a named value (like -EINVAL) and checks against a
> negative value (not -1).

Right, makes sense.

>> +}
>> +
>>   /**
>>    * nand_block_bad - [DEFAULT] Read bad block marker from the chip
>>    * @chip: NAND chip object
>> @@ -294,19 +319,14 @@ static void nand_release_device(struct nand_chip *chip)
>>    */
>>   static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>>   {
>> -	struct mtd_info *mtd = nand_to_mtd(chip);
>> -	int page, page_end, res;
>> +	int page_offset;
>> +	int res, first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> 
> Maybe:
> 
>          int first_page, page_offset;
>          int res;
>          u8 bad;
> 
>          first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
>          page_offset = nand_bbm_get_next_page(chip, -1);

Looks better.

>>   	u8 bad;
>>   
>> -	if (chip->options & NAND_BBM_LASTPAGE)
>> -		ofs += mtd->erasesize - mtd->writesize;
>> +	page_offset = nand_bbm_get_next_page(chip, -1);
>>   
>> -	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
>> -	page_end = page + (((chip->options & NAND_BBM_FIRSTPAGE) &&
>> -			    (chip->options & NAND_BBM_SECONDPAGE)) ? 2 : 1);
>> -
>> -	for (; page < page_end; page++) {
>> -		res = chip->ecc.read_oob(chip, page);
>> +	while (page_offset != -1) {
>> +		res = chip->ecc.read_oob(chip, first_page + page_offset);
>>   		if (res < 0)
>>   			return res;
>>   
>> @@ -318,6 +338,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
>>   			res = hweight8(bad) < chip->badblockbits;
>>   		if (res)
>>   			return res;
>> +
>> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>>   	}
>>   
>>   	return 0;
>> @@ -528,7 +550,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>>   	struct mtd_info *mtd = nand_to_mtd(chip);
>>   	struct mtd_oob_ops ops;
>>   	uint8_t buf[2] = { 0, 0 };
>> -	int ret = 0, res, i = 0;
>> +	int ret = 0, res, page_offset;
>>   
>>   	memset(&ops, 0, sizeof(ops));
>>   	ops.oobbuf = buf;
>> @@ -541,18 +563,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs)
>>   	}
>>   	ops.mode = MTD_OPS_PLACE_OOB;
>>   
>> -	/* Write to first/last page(s) if necessary */
>> -	if (chip->options & NAND_BBM_LASTPAGE)
>> -		ofs += mtd->erasesize - mtd->writesize;
>> -	do {
>> -		res = nand_do_write_oob(chip, ofs, &ops);
>> +	page_offset = nand_bbm_get_next_page(chip, -1);
>> +
>> +	while (page_offset != -1) {
>> +		res = nand_do_write_oob(chip,
>> +					ofs + page_offset * mtd->writesize,
>> +					&ops);
>> +
>>   		if (!ret)
>>   			ret = res;
>>   
>> -		i++;
>> -		ofs += mtd->writesize;
>> -	} while ((chip->options & NAND_BBM_FIRSTPAGE) &&
>> -		 (chip->options & NAND_BBM_SECONDPAGE) && i < 2);
>> +		page_offset = nand_bbm_get_next_page(chip, page_offset);
>> +	}
>>   
>>   	return ret;
>>   }
>> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
>> index 7463afddc7ac..09603c502931 100644
>> --- a/drivers/mtd/nand/raw/nand_bbt.c
>> +++ b/drivers/mtd/nand/raw/nand_bbt.c
>> @@ -415,11 +415,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
>>   
>>   /* Scan a given block partially */
>>   static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>> -			   loff_t offs, uint8_t *buf, int numpages)
>> +			   loff_t offs, uint8_t *buf)
>>   {
>>   	struct mtd_info *mtd = nand_to_mtd(this);
>> +
>>   	struct mtd_oob_ops ops;
>> -	int j, ret;
>> +	int ret, page_offset;
>>   
>>   	ops.ooblen = mtd->oobsize;
>>   	ops.oobbuf = buf;
>> @@ -427,12 +428,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>>   	ops.datbuf = NULL;
>>   	ops.mode = MTD_OPS_PLACE_OOB;
>>   
>> -	for (j = 0; j < numpages; j++) {
>> +	page_offset = nand_bbm_get_next_page(this, -1);
>> +
>> +	while (page_offset != -1) {
>>   		/*
>>   		 * Read the full oob until read_oob is fixed to handle single
>>   		 * byte reads for 16 bit buswidth.
>>   		 */
>> -		ret = mtd_read_oob(mtd, offs, &ops);
>> +		ret = mtd_read_oob(mtd, offs + page_offset * mtd->writesize,
> 
> Can you add '(' & ')' please?

Sure

>> +				   &ops);
>>   		/* Ignore ECC errors when checking for BBM */
>>   		if (ret && !mtd_is_bitflip_or_eccerr(ret))
>>   			return ret;
>> @@ -440,8 +444,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
>>   		if (check_short_pattern(buf, bd))
>>   			return 1;
>>   
>> -		offs += mtd->writesize;
>> +		page_offset = nand_bbm_get_next_page(this, page_offset);
>>   	}
>> +
>>   	return 0;
>>   }
>>   
>> @@ -460,18 +465,11 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>>   		      struct nand_bbt_descr *bd, int chip)
>>   {
>>   	struct mtd_info *mtd = nand_to_mtd(this);
>> -	int i, numblocks, numpages;
>> -	int startblock;
>> +	int i, numblocks, startblock;
>>   	loff_t from;
>>   
>>   	pr_info("Scanning device for bad blocks\n");
>>   
>> -	if ((this->options & NAND_BBM_FIRSTPAGE) &&
>> -	    (this->options & NAND_BBM_SECONDPAGE))
>> -		numpages = 2;
>> -	else
>> -		numpages = 1;
>> -
>>   	if (chip == -1) {
>>   		numblocks = mtd->size >> this->bbt_erase_shift;
>>   		startblock = 0;
>> @@ -488,15 +486,12 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
>>   		from = (loff_t)startblock << this->bbt_erase_shift;
>>   	}
>>   
>> -	if (this->options & NAND_BBM_LASTPAGE)
>> -		from += mtd->erasesize - (mtd->writesize * numpages);
>> -
>>   	for (i = startblock; i < numblocks; i++) {
>>   		int ret;
>>   
>>   		BUG_ON(bd->options & NAND_BBT_NO_OOB);
>>   
>> -		ret = scan_block_fast(this, bd, from, buf, numpages);
>> +		ret = scan_block_fast(this, bd, from, buf);
>>   		if (ret < 0)
>>   			return ret;
>>   
> 
> 
> 
> 
> Thanks,
> Miquèl
> 
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 1/7] mtd: rawnand: Always store info about bad block markers in chip struct
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-04-17 10:03     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:03 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, David Woodhouse, Brian Norris, Marek Vasut,
	linux-mtd, linux-kernel

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:39 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> The information about where the manufacturer puts the bad block
> markers inside the bad block and in the OOB data is stored in
> different places. Let's move this information to nand_chip.options
> and nand_chip.badblockpos.
> 
> As this chip-specific information is not directly related to the
> bad block table (BBT), we also rename the flags to NAND_BBM_*.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

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

* Re: [PATCH v4 1/7] mtd: rawnand: Always store info about bad block markers in chip struct
@ 2019-04-17 10:03     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:03 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:39 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> The information about where the manufacturer puts the bad block
> markers inside the bad block and in the OOB data is stored in
> different places. Let's move this information to nand_chip.options
> and nand_chip.badblockpos.
> 
> As this chip-specific information is not directly related to the
> bad block table (BBT), we also rename the flags to NAND_BBM_*.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
  2019-03-21  8:47       ` Schrempf Frieder
@ 2019-04-17 10:04         ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:04 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, Kyungmin Park, David Woodhouse,
	Brian Norris, Marek Vasut, linux-mtd, linux-kernel

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Thu, 21 Mar
2019 08:47:52 +0000:

> On 04.03.19 11:58, Miquel Raynal wrote:
> > Hi Frieder,
> > 
> > Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> > 2019 10:42:41 +0000:
> >   
> >> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> >>
> >> The information about where the manufacturer puts the bad block
> >> markers inside the bad block and in the OOB data is stored in
> >> different places. Let's move this information to the chip struct,
> >> as we did it for rawnand.
> >>
> >> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> >> ---
> >>   drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
> >>   drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
> >>   include/linux/mtd/onenand.h             | 3 +++
> >>   3 files changed, 7 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> >> index 4ca4b194e7d7..f41d76248550 100644
> >> --- a/drivers/mtd/nand/onenand/onenand_base.c
> >> +++ b/drivers/mtd/nand/onenand/onenand_base.c
> >> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
> >>                   bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
> >>   
> >>           /* We write two bytes, so we don't have to mess with 16-bit access */
> >> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
> >> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
> >>   	/* FIXME : What to do when marking SLC block in partition
> >>   	 * 	   with MLC erasesize? For now, it is not advisable to
> >>   	 *	   create partitions containing both SLC and MLC regions.
> >> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
> >>   	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
> >>   		this->unlock_all(mtd);
> >>   
> >> +	/* Set the bad block marker position */
> >> +	this->badblockpos = ONENAND_BADBLOCK_POS;
> >> +
> >>   	ret = this->scan_bbt(mtd);
> >>   	if ((!FLEXONENAND(this)) || ret)
> >>   		return ret;
> >> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
> >> index dde20487937d..57c31c81be18 100644
> >> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
> >> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
> >> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
> >>   	if (!bbm->bbt)
> >>   		return -ENOMEM;
> >>   
> >> -	/* Set the bad block position */
> >> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
> >> -
> >>   	/* Set erase shift */
> >>   	bbm->bbt_erase_shift = this->erase_shift;
> >>   
> >> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
> >> index 0aaa98b219a4..e03aea7f7e61 100644
> >> --- a/include/linux/mtd/onenand.h
> >> +++ b/include/linux/mtd/onenand.h
> >> @@ -94,6 +94,7 @@ struct onenand_chip {
> >>   	unsigned int		technology;
> >>   	unsigned int		density_mask;
> >>   	unsigned int		options;
> >> +	int			badblockpos;  
> > 
> > Any reason not to unsign this field?  
> 
> It was signed so far, but you're right that it makes more sense to 
> unsign it.

With this addressed please add my:

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

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

* Re: [PATCH v4 2/7] mtd: onenand: Store bad block marker position in chip struct
@ 2019-04-17 10:04         ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:04 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, Kyungmin Park,
	linux-mtd, Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Thu, 21 Mar
2019 08:47:52 +0000:

> On 04.03.19 11:58, Miquel Raynal wrote:
> > Hi Frieder,
> > 
> > Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
> > 2019 10:42:41 +0000:
> >   
> >> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> >>
> >> The information about where the manufacturer puts the bad block
> >> markers inside the bad block and in the OOB data is stored in
> >> different places. Let's move this information to the chip struct,
> >> as we did it for rawnand.
> >>
> >> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> >> ---
> >>   drivers/mtd/nand/onenand/onenand_base.c | 5 ++++-
> >>   drivers/mtd/nand/onenand/onenand_bbt.c  | 3 ---
> >>   include/linux/mtd/onenand.h             | 3 +++
> >>   3 files changed, 7 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
> >> index 4ca4b194e7d7..f41d76248550 100644
> >> --- a/drivers/mtd/nand/onenand/onenand_base.c
> >> +++ b/drivers/mtd/nand/onenand/onenand_base.c
> >> @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
> >>                   bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
> >>   
> >>           /* We write two bytes, so we don't have to mess with 16-bit access */
> >> -        ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
> >> +        ofs += mtd->oobsize + (this->badblockpos & ~0x01);
> >>   	/* FIXME : What to do when marking SLC block in partition
> >>   	 * 	   with MLC erasesize? For now, it is not advisable to
> >>   	 *	   create partitions containing both SLC and MLC regions.
> >> @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
> >>   	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
> >>   		this->unlock_all(mtd);
> >>   
> >> +	/* Set the bad block marker position */
> >> +	this->badblockpos = ONENAND_BADBLOCK_POS;
> >> +
> >>   	ret = this->scan_bbt(mtd);
> >>   	if ((!FLEXONENAND(this)) || ret)
> >>   		return ret;
> >> diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c
> >> index dde20487937d..57c31c81be18 100644
> >> --- a/drivers/mtd/nand/onenand/onenand_bbt.c
> >> +++ b/drivers/mtd/nand/onenand/onenand_bbt.c
> >> @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
> >>   	if (!bbm->bbt)
> >>   		return -ENOMEM;
> >>   
> >> -	/* Set the bad block position */
> >> -	bbm->badblockpos = ONENAND_BADBLOCK_POS;
> >> -
> >>   	/* Set erase shift */
> >>   	bbm->bbt_erase_shift = this->erase_shift;
> >>   
> >> diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
> >> index 0aaa98b219a4..e03aea7f7e61 100644
> >> --- a/include/linux/mtd/onenand.h
> >> +++ b/include/linux/mtd/onenand.h
> >> @@ -94,6 +94,7 @@ struct onenand_chip {
> >>   	unsigned int		technology;
> >>   	unsigned int		density_mask;
> >>   	unsigned int		options;
> >> +	int			badblockpos;  
> > 
> > Any reason not to unsign this field?  
> 
> It was signed so far, but you're right that it makes more sense to 
> unsign it.

With this addressed please add my:

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 3/7] mtd: nand: Cleanup flags and fields for bad block marker position
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-04-17 10:05     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:05 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, David Woodhouse, Brian Norris, Marek Vasut,
	linux-mtd, linux-kernel

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:43 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> Now that we have moved the information to the chip level, let's
> remove all the unused flags and fields.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

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

* Re: [PATCH v4 3/7] mtd: nand: Cleanup flags and fields for bad block marker position
@ 2019-04-17 10:05     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:05 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:43 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> Now that we have moved the information to the chip level, let's
> remove all the unused flags and fields.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 4/7] mtd: nand: Make flags for bad block marker position more granular
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-04-17 10:05     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:05 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, David Woodhouse, Brian Norris, Marek Vasut,
	linux-mtd, linux-kernel

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> To be able to check and set bad block markers in the first and
> second page of a block independently of each other, we create
> separate flags for both cases.
> 
> Previously NAND_BBM_SECONDPAGE meant, that both, the first and the
> second page were used. With this patch NAND_BBM_FIRSTPAGE stands for
> using the first page and NAND_BBM_SECONDPAGE for using the second
> page.
> 
> This patch is only for preparation of subsequent changes and does
> not implement the logic to actually handle both flags separately.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

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

* Re: [PATCH v4 4/7] mtd: nand: Make flags for bad block marker position more granular
@ 2019-04-17 10:05     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:05 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> To be able to check and set bad block markers in the first and
> second page of a block independently of each other, we create
> separate flags for both cases.
> 
> Previously NAND_BBM_SECONDPAGE meant, that both, the first and the
> second page were used. With this patch NAND_BBM_FIRSTPAGE stands for
> using the first page and NAND_BBM_SECONDPAGE for using the second
> page.
> 
> This patch is only for preparation of subsequent changes and does
> not implement the logic to actually handle both flags separately.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 6/7] mtd: rawnand: ESMT: Also use the last page for bad block markers
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-04-17 10:08     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:08 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, linux-mtd, David Woodhouse,
	Brian Norris, Marek Vasut

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> It is known that some ESMT SLC NANDs have been shipped
> with the factory bad block markers in the first or last page
> of the block, instead of the first or second page. To be on
> the safe side, let's check all three locations.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/nand_esmt.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
> index 99a8092969a7..b37e0b5af5ae 100644
> --- a/drivers/mtd/nand/raw/nand_esmt.c
> +++ b/drivers/mtd/nand/raw/nand_esmt.c
> @@ -36,7 +36,14 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
>  static int esmt_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> -		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
> +		/*
> +		 * It is known that some ESMT SLC NANDs have been shipped
> +		 * with the factory bad block markers in the first or last page
> +		 * of the block, instead of the first or second page. To be on
> +		 * the safe side, let's check all three locations.
> +		 */
> +		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
> +				 NAND_BBM_LASTPAGE;
>  
>  	return 0;
>  }


Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

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

* Re: [PATCH v4 6/7] mtd: rawnand: ESMT: Also use the last page for bad block markers
@ 2019-04-17 10:08     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:08 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:45 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> It is known that some ESMT SLC NANDs have been shipped
> with the factory bad block markers in the first or last page
> of the block, instead of the first or second page. To be on
> the safe side, let's check all three locations.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/nand_esmt.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
> index 99a8092969a7..b37e0b5af5ae 100644
> --- a/drivers/mtd/nand/raw/nand_esmt.c
> +++ b/drivers/mtd/nand/raw/nand_esmt.c
> @@ -36,7 +36,14 @@ static void esmt_nand_decode_id(struct nand_chip *chip)
>  static int esmt_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> -		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
> +		/*
> +		 * It is known that some ESMT SLC NANDs have been shipped
> +		 * with the factory bad block markers in the first or last page
> +		 * of the block, instead of the first or second page. To be on
> +		 * the safe side, let's check all three locations.
> +		 */
> +		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
> +				 NAND_BBM_LASTPAGE;
>  
>  	return 0;
>  }


Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v4 7/7] mtd: rawnand: AMD: Also use the last page for bad block markers
  2019-02-18 10:42   ` Schrempf Frieder
@ 2019-04-17 10:08     ` Miquel Raynal
  -1 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:08 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, linux-mtd, David Woodhouse,
	Brian Norris, Marek Vasut

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:46 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> According to the datasheet of some Cypress SLC NANDs, the bad
> block markers can be in the first, second or last page of a block.
> So let's check all three locations.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/nand_amd.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
> index 6202cbf7ee8d..2ffcddff3e27 100644
> --- a/drivers/mtd/nand/raw/nand_amd.c
> +++ b/drivers/mtd/nand/raw/nand_amd.c
> @@ -40,7 +40,13 @@ static void amd_nand_decode_id(struct nand_chip *chip)
>  static int amd_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> -		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
> +		/*
> +		 * According to the datasheet of some Cypress SLC NANDs,
> +		 * the bad block markers can be in the first, second or last
> +		 * page of a block. So let's check all three locations.
> +		 */
> +		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
> +				 NAND_BBM_LASTPAGE;
>  
>  	return 0;
>  }


Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

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

* Re: [PATCH v4 7/7] mtd: rawnand: AMD: Also use the last page for bad block markers
@ 2019-04-17 10:08     ` Miquel Raynal
  0 siblings, 0 replies; 36+ messages in thread
From: Miquel Raynal @ 2019-04-17 10:08 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: bbrezillon, richard, linux-kernel, Marek Vasut, linux-mtd,
	Brian Norris, David Woodhouse

Hi Frieder,

Schrempf Frieder <frieder.schrempf@kontron.de> wrote on Mon, 18 Feb
2019 10:42:46 +0000:

> From: Frieder Schrempf <frieder.schrempf@kontron.de>
> 
> According to the datasheet of some Cypress SLC NANDs, the bad
> block markers can be in the first, second or last page of a block.
> So let's check all three locations.
> 
> Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
> Reviewed-by: Boris Brezillon <bbrezillon@kernel.org>
> ---
>  drivers/mtd/nand/raw/nand_amd.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
> index 6202cbf7ee8d..2ffcddff3e27 100644
> --- a/drivers/mtd/nand/raw/nand_amd.c
> +++ b/drivers/mtd/nand/raw/nand_amd.c
> @@ -40,7 +40,13 @@ static void amd_nand_decode_id(struct nand_chip *chip)
>  static int amd_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> -		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
> +		/*
> +		 * According to the datasheet of some Cypress SLC NANDs,
> +		 * the bad block markers can be in the first, second or last
> +		 * page of a block. So let's check all three locations.
> +		 */
> +		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE |
> +				 NAND_BBM_LASTPAGE;
>  
>  	return 0;
>  }


Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2019-04-17 10:08 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-18 10:42 [PATCH v4 0/7] mtd: rawnand: Support bad block markers in first, second or last page Schrempf Frieder
2019-02-18 10:42 ` Schrempf Frieder
2019-02-18 10:42 ` [PATCH v4 1/7] mtd: rawnand: Always store info about bad block markers in chip struct Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-04-17 10:03   ` Miquel Raynal
2019-04-17 10:03     ` Miquel Raynal
2019-02-18 10:42 ` [PATCH v4 2/7] mtd: onenand: Store bad block marker position " Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-03-04 10:58   ` Miquel Raynal
2019-03-04 10:58     ` Miquel Raynal
2019-03-21  8:47     ` Schrempf Frieder
2019-03-21  8:47       ` Schrempf Frieder
2019-04-17 10:04       ` Miquel Raynal
2019-04-17 10:04         ` Miquel Raynal
2019-02-18 10:42 ` [PATCH v4 3/7] mtd: nand: Cleanup flags and fields for bad block marker position Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-04-17 10:05   ` Miquel Raynal
2019-04-17 10:05     ` Miquel Raynal
2019-02-18 10:42 ` [PATCH v4 4/7] mtd: nand: Make flags for bad block marker position more granular Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-04-17 10:05   ` Miquel Raynal
2019-04-17 10:05     ` Miquel Raynal
2019-02-18 10:42 ` [PATCH v4 5/7] mtd: rawnand: Support bad block markers in first, second or last page Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-03-04 11:21   ` Miquel Raynal
2019-03-04 11:21     ` Miquel Raynal
2019-03-21  9:04     ` Schrempf Frieder
2019-03-21  9:04       ` Schrempf Frieder
2019-02-18 10:42 ` [PATCH v4 6/7] mtd: rawnand: ESMT: Also use the last page for bad block markers Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-04-17 10:08   ` Miquel Raynal
2019-04-17 10:08     ` Miquel Raynal
2019-02-18 10:42 ` [PATCH v4 7/7] mtd: rawnand: AMD: " Schrempf Frieder
2019-02-18 10:42   ` Schrempf Frieder
2019-04-17 10:08   ` Miquel Raynal
2019-04-17 10:08     ` Miquel Raynal

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.