All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block
@ 2010-06-23 20:36 Brian Norris
  2010-06-25 21:36 ` [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Brian Norris @ 2010-06-23 20:36 UTC (permalink / raw)
  To: linux-mtd; +Cc: Brian Norris

NAND_BB_LAST_PAGE used to be in nand.h, but it pertained to bad block
management and so belongs next to NAND_BBT_SCAN2NDPAGE in bbm.h. Also,
its previous flag value (0x00000400) conflicted with NAND_BBT_SCANALLPAGES
so I changed its value to 0x00008000. All uses of the name were modified to
provide consistency with other "NAND_BBT_*" flags.

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |    6 +++---
 drivers/mtd/nand/nand_bbt.c  |    2 +-
 include/linux/mtd/bbm.h      |    2 ++
 include/linux/mtd/nand.h     |    2 --
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 4a7b864..e6cf9ae 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -347,7 +347,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -399,7 +399,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	uint8_t buf[2] = { 0, 0 };
 	int block, ret;
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	/* Get block number */
@@ -2946,7 +2946,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
-		chip->options |= NAND_BB_LAST_PAGE;
+		chip->options |= NAND_BBT_SCANLASTPAGE;
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ad97c0c..71d83be 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -432,7 +432,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
 	}
 
-	if (this->options & NAND_BB_LAST_PAGE)
+	if (this->options & NAND_BBT_SCANLASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * len);
 
 	for (i = startblock; i < numblocks;) {
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 9c3757c..8ad0b86 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -82,6 +82,8 @@ struct nand_bbt_descr {
 #define NAND_BBT_SAVECONTENT	0x00002000
 /* Search good / bad pattern on the first and the second page */
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
+/* Search good / bad pattern on the last page of the eraseblock */
+#define NAND_BBT_SCANLASTPAGE	0x00008000
 
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index a81b185..50f3aa0 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -181,8 +181,6 @@ typedef enum {
 #define NAND_NO_READRDY		0x00000100
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
-/* Chip stores bad block marker on the last page of the eraseblock */
-#define NAND_BB_LAST_PAGE	0x00000400
 
 /* Device is one of 'new' xD cards that expose fake nand command set */
 #define NAND_BROKEN_XD		0x00000400
-- 
1.7.1

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

* [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6
  2010-06-23 20:36 [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Brian Norris
@ 2010-06-25 21:36 ` Brian Norris
  2010-07-13  8:21   ` Artem Bityutskiy
  2010-07-08  9:15 ` [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Artem Bityutskiy
  2010-07-13  8:01 ` Artem Bityutskiy
  2 siblings, 1 reply; 16+ messages in thread
From: Brian Norris @ 2010-06-25 21:36 UTC (permalink / raw)
  To: linux-mtd; +Cc: Brian Norris

Some level of support for various scanning locations was already built in,
but this required clean-up. First, BB marker location cannot be determined
_only_ by the page size. Instead, I implemented some heuristic detection
based on data sheets from various manufacturers (all found in
nand_base.c:nand_get_flash_type()).

Second, once these options were identified, they were not handled properly
by nand_bbt.c:nand_default_bbt(). I believe there are only 5 combinations
of page location/byte offset, so I updated the nand_bbt_desc structs
accordingly.

I have tested these changes with several chips, but particularly a Micron
29F8G08MAA chip. We use a memory-based, not flash-based, BBT; hence the
edits only to the "memory_based" side of things. Most edits could be
applicable to both, but I can't verify that. For instance, I do not
understand why the small discrepancies between the "memory_based" and
"flash_based" nand_bbt_descr structs.

Finally, please provide any feedback you can. I'm sure there's something
I have overlooked, but I feel this is a step in the right direction.

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   23 +++++++++++++++++++----
 drivers/mtd/nand/nand_bbt.c  |   41 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e6cf9ae..2d1ee3c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2920,9 +2920,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
 
 	/* Set the bad block position */
-	chip->badblockpos = mtd->writesize > 512 ?
-		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-	chip->badblockbits = 8;
+	chip->badblockpos = (!(busw & NAND_BUSWIDTH_16) &&
+			(*maf_id == NAND_MFR_STMICRO ||
+			 (*maf_id == NAND_MFR_SAMSUNG &&
+			  mtd->writesize == 512) ||
+			 *maf_id == NAND_MFR_AMD))
+		? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;
+
 
 	/* Get chip options, preserve non chip based options */
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
@@ -2941,12 +2945,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	/*
 	 * Bad block marker is stored in the last page of each block
-	 * on Samsung and Hynix MLC devices
+	 * on Samsung and Hynix MLC devices; stored in first two pages 
+	 * of each block on Micron devices with 2KiB pages and on 
+	 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only 
+	 * the first page.
 	 */
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
 		chip->options |= NAND_BBT_SCANLASTPAGE;
+	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+				(*maf_id == NAND_MFR_SAMSUNG ||
+				 *maf_id == NAND_MFR_HYNIX ||
+				 *maf_id == NAND_MFR_AMD)) ||
+			(mtd->writesize == 2048 &&
+			 *maf_id == NAND_MFR_MICRON))
+		chip->options |= NAND_BBT_SCAN2NDPAGE;
+
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 71d83be..1719c56 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1093,29 +1093,50 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static struct nand_bbt_descr smallpage_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.options = 0,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_SMALL_BADBLOCK_POS,
+	.len = 2,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr largepage_memorybased = {
 	.options = 0,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
+static struct nand_bbt_descr largepage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr lastpage_memorybased = {
+	.options = NAND_BBT_SCANLASTPAGE,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
 static struct nand_bbt_descr largepage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
@@ -1197,8 +1218,14 @@ int nand_default_bbt(struct mtd_info *mtd)
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
 		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->writesize > 512) ?
-			    &largepage_memorybased : &smallpage_memorybased;
+			if (this->options & NAND_BBT_SCANLASTPAGE)
+				this->badblock_pattern = &lastpage_memorybased;
+			else if (this->options & NAND_BBT_SCAN2NDPAGE)
+				this->badblock_pattern = this->badblockpos == NAND_SMALL_BADBLOCK_POS ? 
+					&smallpage_scan2nd_memorybased : &largepage_scan2nd_memorybased;
+			else
+				this->badblock_pattern = this->badblockpos == NAND_SMALL_BADBLOCK_POS ? 
+					&smallpage_memorybased : &largepage_memorybased;
 		}
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
-- 
1.7.1

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

* Re: [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block
  2010-06-23 20:36 [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Brian Norris
  2010-06-25 21:36 ` [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
@ 2010-07-08  9:15 ` Artem Bityutskiy
  2010-07-13  8:01 ` Artem Bityutskiy
  2 siblings, 0 replies; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-08  9:15 UTC (permalink / raw)
  To: Brian Norris; +Cc: linux-mtd

On Wed, 2010-06-23 at 13:36 -0700, Brian Norris wrote:
> NAND_BB_LAST_PAGE used to be in nand.h, but it pertained to bad block
> management and so belongs next to NAND_BBT_SCAN2NDPAGE in bbm.h. Also,
> its previous flag value (0x00000400) conflicted with NAND_BBT_SCANALLPAGES
> so I changed its value to 0x00008000. All uses of the name were modified to
> provide consistency with other "NAND_BBT_*" flags.
> 
> Signed-off-by: Brian Norris <norris@broadcom.com>

Pushed to l2-mtd-2.6.git / master, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block
  2010-06-23 20:36 [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Brian Norris
  2010-06-25 21:36 ` [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
  2010-07-08  9:15 ` [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Artem Bityutskiy
@ 2010-07-13  8:01 ` Artem Bityutskiy
  2 siblings, 0 replies; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-13  8:01 UTC (permalink / raw)
  To: Brian Norris; +Cc: linux-mtd

On Wed, 2010-06-23 at 13:36 -0700, Brian Norris wrote:
> NAND_BB_LAST_PAGE used to be in nand.h, but it pertained to bad block
> management and so belongs next to NAND_BBT_SCAN2NDPAGE in bbm.h. Also,
> its previous flag value (0x00000400) conflicted with NAND_BBT_SCANALLPAGES
> so I changed its value to 0x00008000. All uses of the name were modified to
> provide consistency with other "NAND_BBT_*" flags.
> 
> Signed-off-by: Brian Norris <norris@broadcom.com>

Pushed to l2-mtd-2.6.git / master, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6
  2010-06-25 21:36 ` [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
@ 2010-07-13  8:21   ` Artem Bityutskiy
  2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
  0 siblings, 1 reply; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-13  8:21 UTC (permalink / raw)
  To: Brian Norris; +Cc: linux-mtd

On Fri, 2010-06-25 at 14:36 -0700, Brian Norris wrote:
> @@ -2920,9 +2920,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
>  		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
>  
>  	/* Set the bad block position */
> -	chip->badblockpos = mtd->writesize > 512 ?
> -		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
> -	chip->badblockbits = 8;
> +	chip->badblockpos = (!(busw & NAND_BUSWIDTH_16) &&
> +			(*maf_id == NAND_MFR_STMICRO ||
> +			 (*maf_id == NAND_MFR_SAMSUNG &&
> +			  mtd->writesize == 512) ||
> +			 *maf_id == NAND_MFR_AMD))
> +		? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;

I'd prefer if () else, ? : is not appropriate for such huge conditions.

Nevertheless, you patch looks indeed like a step in the right direction,
but I cannot really test it and do not have time to review.

But could you please re-send it without trailing white-spaces - I'll put
it to my l2 tree then? You can do a 'git am' to your own patches - it'll
check for trailing white-spaces for you.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* [PATCH v2 0/2] Improved BB Scanning
  2010-07-13  8:21   ` Artem Bityutskiy
@ 2010-07-13 22:12     ` Brian Norris
  2010-07-13 22:13       ` [PATCH v2 1/2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
                         ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Brian Norris @ 2010-07-13 22:12 UTC (permalink / raw)
  To: linux-mtd
  Cc: Maxim Levitsky, Thomas Gleixner, David Woodhouse, Brian Norris,
	Artem Bityutskiy

This is a two-patch correction and update to my previous attempt
to address a few issues with bad block scanning. Overall, they should
help renovate some incorrect and unwieldy code.

I included the top few maintainers from get_maintainers.pl. Sorry if these
were incorrect addressees.

Brian Norris (2):
  mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6
  mtd/nand: More BB Detection, dynamic scan options

 drivers/mtd/nand/nand_base.c |   38 ++++++++++++++++--
 drivers/mtd/nand/nand_bbt.c  |   89 +++++++++++++++++++++++++++++------------
 include/linux/mtd/bbm.h      |    4 ++
 3 files changed, 101 insertions(+), 30 deletions(-)

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

* [PATCH v2 1/2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6
  2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
@ 2010-07-13 22:13       ` Brian Norris
  2010-07-13 22:13       ` [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options Brian Norris
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2010-07-13 22:13 UTC (permalink / raw)
  To: linux-mtd
  Cc: Maxim Levitsky, Thomas Gleixner, David Woodhouse, Brian Norris,
	Artem Bityutskiy

Some level of support for various scanning locations was already built in,
but this required clean-up. First, BB marker location cannot be determined
_only_ by the page size. Instead, I implemented some heuristic detection
based on data sheets from various manufacturers (all found in
nand_base.c:nand_get_flash_type()).

Second, once these options were identified, they were not handled properly
by nand_bbt.c:nand_default_bbt(). I updated the static nand_bbt_desc structs
to reflect the need for more combinations of detection. The memory allocation
here probably needs to be done dynamically in the very near future (see next
patches).

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   24 ++++++++++++++++++---
 drivers/mtd/nand/nand_bbt.c  |   45 +++++++++++++++++++++++++++++++++++------
 2 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e6cf9ae..bd69790 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2920,9 +2920,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
 
 	/* Set the bad block position */
-	chip->badblockpos = mtd->writesize > 512 ?
-		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-	chip->badblockbits = 8;
+	if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO ||
+				(*maf_id == NAND_MFR_SAMSUNG &&
+				 mtd->writesize == 512) ||
+				*maf_id == NAND_MFR_AMD))
+		chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
+	else
+		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+
 
 	/* Get chip options, preserve non chip based options */
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
@@ -2941,12 +2946,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	/*
 	 * Bad block marker is stored in the last page of each block
-	 * on Samsung and Hynix MLC devices
+	 * on Samsung and Hynix MLC devices; stored in first two pages
+	 * of each block on Micron devices with 2KiB pages and on
+	 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only
+	 * the first page.
 	 */
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
 		chip->options |= NAND_BBT_SCANLASTPAGE;
+	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+				(*maf_id == NAND_MFR_SAMSUNG ||
+				 *maf_id == NAND_MFR_HYNIX ||
+				 *maf_id == NAND_MFR_AMD)) ||
+			(mtd->writesize == 2048 &&
+			 *maf_id == NAND_MFR_MICRON))
+		chip->options |= NAND_BBT_SCAN2NDPAGE;
+
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 71d83be..ec1700e 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1093,29 +1093,50 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static struct nand_bbt_descr smallpage_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.options = 0,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_SMALL_BADBLOCK_POS,
+	.len = 2,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr largepage_memorybased = {
 	.options = 0,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
+static struct nand_bbt_descr largepage_scan2nd_memorybased = {
+	.options = NAND_BBT_SCAN2NDPAGE,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
 
+static struct nand_bbt_descr lastpage_memorybased = {
+	.options = NAND_BBT_SCANLASTPAGE,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
 static struct nand_bbt_descr largepage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.pattern = scan_ff_pattern
 };
@@ -1197,8 +1218,18 @@ int nand_default_bbt(struct mtd_info *mtd)
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
 		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->writesize > 512) ?
-			    &largepage_memorybased : &smallpage_memorybased;
+			if (this->options & NAND_BBT_SCANLASTPAGE)
+				this->badblock_pattern = &lastpage_memorybased;
+			else if (this->options & NAND_BBT_SCAN2NDPAGE)
+				this->badblock_pattern = this->badblockpos ==
+					NAND_SMALL_BADBLOCK_POS ?
+					&smallpage_scan2nd_memorybased :
+					&largepage_scan2nd_memorybased;
+			else
+				this->badblock_pattern = this->badblockpos ==
+					NAND_SMALL_BADBLOCK_POS ?
+					&smallpage_memorybased :
+					&largepage_memorybased;
 		}
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
-- 
1.7.0.4

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

* [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options
  2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
  2010-07-13 22:13       ` [PATCH v2 1/2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
@ 2010-07-13 22:13       ` Brian Norris
  2010-07-13 23:56         ` Brian Norris
  2010-07-18 16:38       ` [PATCH v2 0/2] Improved BB Scanning Artem Bityutskiy
  2010-07-21 23:53       ` [PATCH] mtd/nand: Update nand_default_block_markbad() Brian Norris
  3 siblings, 1 reply; 16+ messages in thread
From: Brian Norris @ 2010-07-13 22:13 UTC (permalink / raw)
  To: linux-mtd
  Cc: Maxim Levitsky, Thomas Gleixner, David Woodhouse, Brian Norris,
	Artem Bityutskiy

Added new flag for scanning of both bytes 1 and 6 of the OOB for
a BB marker (instead of simply one or the other).

In order to handle increases in variety of necessary scanning patterns,
I implemented dynamic memory allocation of nand_bbt_descr structs
in new function 'nand_create_default_bbt_descr()'. This replaces
some increasingly-unwieldy, statically-declared descriptors. It can
replace several more (e.g. "flashbased" structs). However, I do not
test the flashbased options personally.

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   14 +++++
 drivers/mtd/nand/nand_bbt.c  |  116 ++++++++++++++++++++++--------------------
 include/linux/mtd/bbm.h      |    4 ++
 3 files changed, 79 insertions(+), 55 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index bd69790..c2901bd 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2963,6 +2963,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 			 *maf_id == NAND_MFR_MICRON))
 		chip->options |= NAND_BBT_SCAN2NDPAGE;
 
+	/*
+	 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
+	 */
+	if (!(busw & NAND_BUSWIDTH_16) &&
+			*maf_id == NAND_MFR_STMICRO &&
+			mtd->writesize == 2048) {
+		chip->options |= NAND_BBT_SCANBYTE1AND6;
+		chip->badblockpos = 0;
+	}
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
@@ -3322,6 +3331,11 @@ void nand_release(struct mtd_info *mtd)
 	kfree(chip->bbt);
 	if (!(chip->options & NAND_OWN_BUFFERS))
 		kfree(chip->buffers);
+
+	/* Free bad block descriptor memory */
+	if (chip->badblock_pattern && chip->badblock_pattern->options
+			& NAND_BBT_DYNAMICSTRUCT)
+		kfree(chip->badblock_pattern);
 }
 
 EXPORT_SYMBOL_GPL(nand_lock);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ec1700e..474ff66 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -397,12 +397,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
-	else {
-		if (bd->options & NAND_BBT_SCAN2NDPAGE)
-			len = 2;
-		else
-			len = 1;
-	}
+	else if (bd->options & NAND_BBT_SCAN2NDPAGE)
+		len = 2;
+	else
+		len = 1;
 
 	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
 		/* We need only read few bytes from the OOB area */
@@ -447,6 +445,24 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		if (ret < 0)
 			return ret;
 
+		/* Check if we need a second scan for the 6th byte
+		 * Perhaps there is a more efficient way of doing this?
+		 */
+		if (!ret && bd->options & NAND_BBT_SCANBYTE1AND6) {
+			bd->offs = NAND_SMALL_BADBLOCK_POS;
+			if (bd->options & NAND_BBT_SCANALLPAGES)
+				ret = scan_block_full(mtd, bd, from, buf,
+						readlen, scanlen, len);
+			else
+				ret = scan_block_fast(mtd, bd, from, buf, len);
+
+			/* Reset offset for future scans */
+			bd->offs = NAND_LARGE_BADBLOCK_POS;
+
+			if (ret < 0)
+				return ret;
+		}
+
 		if (ret) {
 			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
 			printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
@@ -1092,41 +1108,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
  * while scanning a device for factory marked good / bad blocks. */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
-static struct nand_bbt_descr smallpage_memorybased = {
-	.options = 0,
-	.offs = NAND_SMALL_BADBLOCK_POS,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_SMALL_BADBLOCK_POS,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_memorybased = {
-	.options = 0,
-	.offs = NAND_LARGE_BADBLOCK_POS,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_scan2nd_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_LARGE_BADBLOCK_POS,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr lastpage_memorybased = {
-	.options = NAND_BBT_SCANLASTPAGE,
-	.offs = 0,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = NAND_SMALL_BADBLOCK_POS,
@@ -1175,6 +1156,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 	.pattern = mirror_pattern
 };
 
+#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
+		NAND_BBT_SCANBYTE1AND6)
+/**
+ * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
+ * @this:	NAND chip to create descriptor for
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection
+ * based on the properties of "this". The new descriptor is stored in
+ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
+ * passed to this function.
+ *
+ * TODO: Handle other flags, replace other static structs
+ *        (e.g. handle NAND_BBT_FLASH for flash-based BBT,
+ *             replace smallpage_flashbased)
+ *
+ */
+static int nand_create_default_bbt_descr(struct nand_chip *this)
+{
+	struct nand_bbt_descr *bd;
+	if (this->badblock_pattern) {
+		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		return -EINVAL;
+	}
+	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+	if (!bd) {
+		printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+		return -ENOMEM;
+	}
+	bd->options = this->options & BBT_SCAN_OPTIONS;
+	bd->offs = this->badblockpos;
+	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
+	bd->pattern = scan_ff_pattern;
+	bd->options |= NAND_BBT_DYNAMICSTRUCT;
+	this->badblock_pattern = bd;
+	return 0;
+}
+
 /**
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
  * @mtd:	MTD device structure
@@ -1217,20 +1235,8 @@ int nand_default_bbt(struct mtd_info *mtd)
 	} else {
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
-		if (!this->badblock_pattern) {
-			if (this->options & NAND_BBT_SCANLASTPAGE)
-				this->badblock_pattern = &lastpage_memorybased;
-			else if (this->options & NAND_BBT_SCAN2NDPAGE)
-				this->badblock_pattern = this->badblockpos ==
-					NAND_SMALL_BADBLOCK_POS ?
-					&smallpage_scan2nd_memorybased :
-					&largepage_scan2nd_memorybased;
-			else
-				this->badblock_pattern = this->badblockpos ==
-					NAND_SMALL_BADBLOCK_POS ?
-					&smallpage_memorybased :
-					&largepage_memorybased;
-		}
+		if (!this->badblock_pattern)
+			nand_create_default_bbt_descr(this);
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 8ad0b86..a04b962 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -84,6 +84,10 @@ struct nand_bbt_descr {
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
 /* Search good / bad pattern on the last page of the eraseblock */
 #define NAND_BBT_SCANLASTPAGE	0x00008000
+/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
+#define NAND_BBT_SCANBYTE1AND6 0x00100000
+/* The nand_bbt_descr was created dynamicaly and must be freed */
+#define NAND_BBT_DYNAMICSTRUCT 0x00200000
 
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
-- 
1.7.0.4

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

* Re: [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options
  2010-07-13 22:13       ` [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options Brian Norris
@ 2010-07-13 23:56         ` Brian Norris
  2010-07-15 19:15           ` [PATCH v3 " Brian Norris
  0 siblings, 1 reply; 16+ messages in thread
From: Brian Norris @ 2010-07-13 23:56 UTC (permalink / raw)
  To: linux-mtd
  Cc: Maxim Levitsky, Thomas Gleixner, David Woodhouse, Brian Norris,
	Artem Bityutskiy

I have a few comments/questions about the following sections.

On 07/13/2010 03:13 PM, Brian Norris wrote:
> Added new flag for scanning of both bytes 1 and 6 of the OOB for
> a BB marker (instead of simply one or the other).

<snip>

> diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
> index ec1700e..474ff66 100644
> --- a/drivers/mtd/nand/nand_bbt.c
> +++ b/drivers/mtd/nand/nand_bbt.c

<snip>

> @@ -447,6 +445,24 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
>   		if (ret<  0)
>   			return ret;
>
> +		/* Check if we need a second scan for the 6th byte
> +		 * Perhaps there is a more efficient way of doing this?
> +		 */
> +		if (!ret&&  bd->options&  NAND_BBT_SCANBYTE1AND6) {
> +			bd->offs = NAND_SMALL_BADBLOCK_POS;
> +			if (bd->options&  NAND_BBT_SCANALLPAGES)
> +				ret = scan_block_full(mtd, bd, from, buf,
> +						readlen, scanlen, len);
> +			else
> +				ret = scan_block_fast(mtd, bd, from, buf, len);
> +
> +			/* Reset offset for future scans */
> +			bd->offs = NAND_LARGE_BADBLOCK_POS;
> +
> +			if (ret<  0)
> +				return ret;
> +		}
> +
>   		if (ret) {
>   			this->bbt[i>>  3] |= 0x03<<  (i&  0x6);
>   			printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",

I realize it's probably not the best practice to just duplicate/modify 
the detection code as I did above. I am trying to find the best place to 
implement the scanning of both bytes 1 and 6 of the OOB. Perhaps 
nand_bbt.c:check_pattern() and check_short_pattern()?

Also, it seems to me that in addition to the main scanning routines, I 
should update the nand_default_block_markbad() function in nand_base.c 
so that it writes its BB marker to the proper bytes in the OOB. Does 
this sound reasonable?

Comments/corrections are appreciated!

Brian

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

* [PATCH v3 2/2] mtd/nand: More BB Detection, dynamic scan options
  2010-07-13 23:56         ` Brian Norris
@ 2010-07-15 19:15           ` Brian Norris
  0 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2010-07-15 19:15 UTC (permalink / raw)
  To: linux-mtd
  Cc: David Woodhouse, Thomas Gleixner, Maxim Levitsky, Brian Norris,
	Artem Bityutskiy

This is a revision to PATCH 2/2 that I sent. Link:
http://lists.infradead.org/pipermail/linux-mtd/2010-July/030911.html

Added new flag for scanning of both bytes 1 and 6 of the OOB for
a BB marker (instead of simply one or the other).

The "check_pattern" and "check_short_pattern" functions were updated
to include support for scanning the two different locations in the OOB.

In order to handle increases in variety of necessary scanning patterns,
I implemented dynamic memory allocation of nand_bbt_descr structs
in new function 'nand_create_default_bbt_descr()'. This replaces
some increasingly-unwieldy, statically-declared descriptors. It can
replace several more (e.g. "flashbased" structs). However, I do not
test the flashbased options personally.

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   14 +++++
 drivers/mtd/nand/nand_bbt.c  |  127 ++++++++++++++++++++++++------------------
 include/linux/mtd/bbm.h      |    4 +
 3 files changed, 90 insertions(+), 55 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index bd69790..c2901bd 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2963,6 +2963,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 			 *maf_id == NAND_MFR_MICRON))
 		chip->options |= NAND_BBT_SCAN2NDPAGE;
 
+	/*
+	 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
+	 */
+	if (!(busw & NAND_BUSWIDTH_16) &&
+			*maf_id == NAND_MFR_STMICRO &&
+			mtd->writesize == 2048) {
+		chip->options |= NAND_BBT_SCANBYTE1AND6;
+		chip->badblockpos = 0;
+	}
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
@@ -3322,6 +3331,11 @@ void nand_release(struct mtd_info *mtd)
 	kfree(chip->bbt);
 	if (!(chip->options & NAND_OWN_BUFFERS))
 		kfree(chip->buffers);
+
+	/* Free bad block descriptor memory */
+	if (chip->badblock_pattern && chip->badblock_pattern->options
+			& NAND_BBT_DYNAMICSTRUCT)
+		kfree(chip->badblock_pattern);
 }
 
 EXPORT_SYMBOL_GPL(nand_lock);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ec1700e..469de17 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -93,6 +93,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
 			return -1;
 	}
 
+	/* Check both positions 1 and 6 for pattern? */
+	if (td->options & NAND_BBT_SCANBYTE1AND6) {
+		if (td->options & NAND_BBT_SCANEMPTY) {
+			p += td->len;
+			end += NAND_SMALL_BADBLOCK_POS - td->offs;
+			/* Check region between positions 1 and 6 */
+			for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
+					i++) {
+				if (*p++ != 0xff)
+					return -1;
+			}
+		}
+		else {
+			p += NAND_SMALL_BADBLOCK_POS - td->offs;
+		}
+		/* Compare the pattern */
+		for (i = 0; i < td->len; i++) {
+			if (p[i] != td->pattern[i])
+				return -1;
+		}
+	}
+
 	if (td->options & NAND_BBT_SCANEMPTY) {
 		p += td->len;
 		end += td->len;
@@ -124,6 +146,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 		if (p[td->offs + i] != td->pattern[i])
 			return -1;
 	}
+	/* Need to check location 1 AND 6? */
+	if (td->options & NAND_BBT_SCANBYTE1AND6) {
+		for (i = 0; i < td->len; i++) {
+			if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
+				return -1;
+		}
+	}
 	return 0;
 }
 
@@ -397,12 +426,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
-	else {
-		if (bd->options & NAND_BBT_SCAN2NDPAGE)
-			len = 2;
-		else
-			len = 1;
-	}
+	else if (bd->options & NAND_BBT_SCAN2NDPAGE)
+		len = 2;
+	else
+		len = 1;
 
 	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
 		/* We need only read few bytes from the OOB area */
@@ -1092,41 +1119,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
  * while scanning a device for factory marked good / bad blocks. */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
-static struct nand_bbt_descr smallpage_memorybased = {
-	.options = 0,
-	.offs = NAND_SMALL_BADBLOCK_POS,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_SMALL_BADBLOCK_POS,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_memorybased = {
-	.options = 0,
-	.offs = NAND_LARGE_BADBLOCK_POS,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_scan2nd_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_LARGE_BADBLOCK_POS,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr lastpage_memorybased = {
-	.options = NAND_BBT_SCANLASTPAGE,
-	.offs = 0,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = NAND_SMALL_BADBLOCK_POS,
@@ -1175,6 +1167,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 	.pattern = mirror_pattern
 };
 
+#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
+		NAND_BBT_SCANBYTE1AND6)
+/**
+ * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
+ * @this:	NAND chip to create descriptor for
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection
+ * based on the properties of "this". The new descriptor is stored in
+ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
+ * passed to this function.
+ *
+ * TODO: Handle other flags, replace other static structs
+ *        (e.g. handle NAND_BBT_FLASH for flash-based BBT,
+ *             replace smallpage_flashbased)
+ *
+ */
+static int nand_create_default_bbt_descr(struct nand_chip *this)
+{
+	struct nand_bbt_descr *bd;
+	if (this->badblock_pattern) {
+		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		return -EINVAL;
+	}
+	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+	if (!bd) {
+		printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+		return -ENOMEM;
+	}
+	bd->options = this->options & BBT_SCAN_OPTIONS;
+	bd->offs = this->badblockpos;
+	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
+	bd->pattern = scan_ff_pattern;
+	bd->options |= NAND_BBT_DYNAMICSTRUCT;
+	this->badblock_pattern = bd;
+	return 0;
+}
+
 /**
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
  * @mtd:	MTD device structure
@@ -1217,20 +1246,8 @@ int nand_default_bbt(struct mtd_info *mtd)
 	} else {
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
-		if (!this->badblock_pattern) {
-			if (this->options & NAND_BBT_SCANLASTPAGE)
-				this->badblock_pattern = &lastpage_memorybased;
-			else if (this->options & NAND_BBT_SCAN2NDPAGE)
-				this->badblock_pattern = this->badblockpos ==
-					NAND_SMALL_BADBLOCK_POS ?
-					&smallpage_scan2nd_memorybased :
-					&largepage_scan2nd_memorybased;
-			else
-				this->badblock_pattern = this->badblockpos ==
-					NAND_SMALL_BADBLOCK_POS ?
-					&smallpage_memorybased :
-					&largepage_memorybased;
-		}
+		if (!this->badblock_pattern)
+			nand_create_default_bbt_descr(this);
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 8ad0b86..a04b962 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -84,6 +84,10 @@ struct nand_bbt_descr {
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
 /* Search good / bad pattern on the last page of the eraseblock */
 #define NAND_BBT_SCANLASTPAGE	0x00008000
+/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
+#define NAND_BBT_SCANBYTE1AND6 0x00100000
+/* The nand_bbt_descr was created dynamicaly and must be freed */
+#define NAND_BBT_DYNAMICSTRUCT 0x00200000
 
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
-- 
1.7.0.4

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

* Re: [PATCH v2 0/2] Improved BB Scanning
  2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
  2010-07-13 22:13       ` [PATCH v2 1/2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
  2010-07-13 22:13       ` [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options Brian Norris
@ 2010-07-18 16:38       ` Artem Bityutskiy
  2010-07-19 19:32         ` Brian Norris
  2010-07-21 23:53       ` [PATCH] mtd/nand: Update nand_default_block_markbad() Brian Norris
  3 siblings, 1 reply; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-18 16:38 UTC (permalink / raw)
  To: Brian Norris; +Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Maxim Levitsky

On Tue, 2010-07-13 at 15:12 -0700, Brian Norris wrote:
> This is a two-patch correction and update to my previous attempt
> to address a few issues with bad block scanning. Overall, they should
> help renovate some incorrect and unwieldy code.
> 
> I included the top few maintainers from get_maintainers.pl. Sorry if these
> were incorrect addressees.
> 
> Brian Norris (2):
>   mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6
>   mtd/nand: More BB Detection, dynamic scan options
> 
>  drivers/mtd/nand/nand_base.c |   38 ++++++++++++++++--
>  drivers/mtd/nand/nand_bbt.c  |   89 +++++++++++++++++++++++++++++------------
>  include/linux/mtd/bbm.h      |    4 ++
>  3 files changed, 101 insertions(+), 30 deletions(-)

I did not _really_ review this, it the patches look good. How did you
test them? Did you test on both large and small page NANDs?

I pushed your patches to my l2-mtd-2.6.git / master

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [PATCH v2 0/2] Improved BB Scanning
  2010-07-18 16:38       ` [PATCH v2 0/2] Improved BB Scanning Artem Bityutskiy
@ 2010-07-19 19:32         ` Brian Norris
  2010-07-21  9:49           ` Artem Bityutskiy
  0 siblings, 1 reply; 16+ messages in thread
From: Brian Norris @ 2010-07-19 19:32 UTC (permalink / raw)
  To: dedekind1; +Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Maxim Levitsky

On 07/18/2010 09:38 AM, Artem Bityutskiy wrote:
> I did not _really_ review this, it the patches look good. How did you
> test them? Did you test on both large and small page NANDs?

I referenced 30+ data sheets (covering 100+ parts), and I tested a 
selection of 10 different chips to varying degrees. Particularly, I 
tested the creation of bad-block descriptors and basic BB scanning on 
three parts:

ST NAND04GW3B2D, 2K page
ST NAND128W3A, 512B page
Samsung K9F1G08U0A, 2K page

To test these, I wrote some fake bad block markers to the flash (in OOB 
bytes 1, 6, and elsewhere) to see if the scanning routine would detect 
them properly. However, this method was somewhat limited because the 
driver I am using has some bugs in its OOB write functionality.

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

* Re: [PATCH v2 0/2] Improved BB Scanning
  2010-07-19 19:32         ` Brian Norris
@ 2010-07-21  9:49           ` Artem Bityutskiy
  2010-07-22 19:44             ` Karl Beldan
  0 siblings, 1 reply; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-21  9:49 UTC (permalink / raw)
  To: Brian Norris; +Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Maxim Levitsky

On Mon, 2010-07-19 at 12:32 -0700, Brian Norris wrote:
> On 07/18/2010 09:38 AM, Artem Bityutskiy wrote:
> > I did not _really_ review this, it the patches look good. How did you
> > test them? Did you test on both large and small page NANDs?
> 
> I referenced 30+ data sheets (covering 100+ parts), and I tested a 
> selection of 10 different chips to varying degrees. Particularly, I 
> tested the creation of bad-block descriptors and basic BB scanning on 
> three parts:
> 
> ST NAND04GW3B2D, 2K page
> ST NAND128W3A, 512B page
> Samsung K9F1G08U0A, 2K page
> 
> To test these, I wrote some fake bad block markers to the flash (in OOB 
> bytes 1, 6, and elsewhere) to see if the scanning routine would detect 
> them properly. However, this method was somewhat limited because the 
> driver I am using has some bugs in its OOB write functionality.

Sounds like you did a lot of work. I'll add this information to the
patch description.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* [PATCH] mtd/nand: Update nand_default_block_markbad()
  2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
                         ` (2 preceding siblings ...)
  2010-07-18 16:38       ` [PATCH v2 0/2] Improved BB Scanning Artem Bityutskiy
@ 2010-07-21 23:53       ` Brian Norris
  2010-07-26  4:30         ` Artem Bityutskiy
  3 siblings, 1 reply; 16+ messages in thread
From: Brian Norris @ 2010-07-21 23:53 UTC (permalink / raw)
  To: Artem Bityutskiy
  Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Brian Norris,
	Maxim Levitsky

This is an update that depends on the previous patches I sent.

We can now write to all the appropriate BB marker locations (i.e.
pages 1 AND 2, bytes 1 AND 6) with nand_default_block_markbad() if
necessary, according to the flags marked in chip->options.

Note that I removed the line:
	ofs += mtd->oobsize;
Unless I am wrong, this line was completely unnecessary in the
first place.

Signed-off-by: Brian Norris <norris@broadcom.com>
---
 drivers/mtd/nand/nand_base.c |   34 ++++++++++++++++++++++++----------
 1 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c2901bd..ee6a6f8 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -397,7 +397,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct nand_chip *chip = mtd->priv;
 	uint8_t buf[2] = { 0, 0 };
-	int block, ret;
+	int block, ret, i = 0;
 
 	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
@@ -411,17 +411,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (chip->options & NAND_USE_FLASH_BBT)
 		ret = nand_update_bbt(mtd, ofs);
 	else {
-		/* We write two bytes, so we dont have to mess with 16 bit
-		 * access
-		 */
 		nand_get_device(chip, mtd, FL_WRITING);
-		ofs += mtd->oobsize;
-		chip->ops.len = chip->ops.ooblen = 2;
-		chip->ops.datbuf = NULL;
-		chip->ops.oobbuf = buf;
-		chip->ops.ooboffs = chip->badblockpos & ~0x01;
 
-		ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+		/* Write to first two pages and to byte 1 and 6 if necessary.
+		 * If we write to more than one location, the first error
+		 * encountered quits the procedure. We write two bytes per
+		 * location, so we dont have to mess with 16 bit access.
+		 */
+		do {
+			chip->ops.len = chip->ops.ooblen = 2;
+			chip->ops.datbuf = NULL;
+			chip->ops.oobbuf = buf;
+			chip->ops.ooboffs = chip->badblockpos & ~0x01;
+
+			ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+
+			if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
+				chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
+					& ~0x01;
+				ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+			}
+			i++;
+			ofs += mtd->writesize;
+		} while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
+				i < 2);
+
 		nand_release_device(mtd);
 	}
 	if (!ret)
-- 
1.7.0.4

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

* Re: [PATCH v2 0/2] Improved BB Scanning
  2010-07-21  9:49           ` Artem Bityutskiy
@ 2010-07-22 19:44             ` Karl Beldan
  0 siblings, 0 replies; 16+ messages in thread
From: Karl Beldan @ 2010-07-22 19:44 UTC (permalink / raw)
  To: dedekind1
  Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Brian Norris,
	Maxim Levitsky

On Wed, Jul 21, 2010 at 11:49 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Mon, 2010-07-19 at 12:32 -0700, Brian Norris wrote:
>> On 07/18/2010 09:38 AM, Artem Bityutskiy wrote:
>> > I did not _really_ review this, it the patches look good. How did you
>> > test them? Did you test on both large and small page NANDs?
>>
>> I referenced 30+ data sheets (covering 100+ parts), and I tested a
>> selection of 10 different chips to varying degrees. Particularly, I
>> tested the creation of bad-block descriptors and basic BB scanning on
>> three parts:
>>
>> ST NAND04GW3B2D, 2K page
>> ST NAND128W3A, 512B page
>> Samsung K9F1G08U0A, 2K page
>>
>> To test these, I wrote some fake bad block markers to the flash (in OOB
>> bytes 1, 6, and elsewhere) to see if the scanning routine would detect
>> them properly. However, this method was somewhat limited because the
>> driver I am using has some bugs in its OOB write functionality.
>
> Sounds like you did a lot of work. I'll add this information to the
> patch description.
>
I haven't seen many nandsim feedback, though it allows precise test scenarios
and easy flash forensics.
Still, FWIW, I too laud the effort.

-- 
Karl

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

* Re: [PATCH] mtd/nand: Update nand_default_block_markbad()
  2010-07-21 23:53       ` [PATCH] mtd/nand: Update nand_default_block_markbad() Brian Norris
@ 2010-07-26  4:30         ` Artem Bityutskiy
  0 siblings, 0 replies; 16+ messages in thread
From: Artem Bityutskiy @ 2010-07-26  4:30 UTC (permalink / raw)
  To: Brian Norris; +Cc: Thomas Gleixner, linux-mtd, David Woodhouse, Maxim Levitsky

On Wed, 2010-07-21 at 16:53 -0700, Brian Norris wrote:
> This is an update that depends on the previous patches I sent.
> 
> We can now write to all the appropriate BB marker locations (i.e.
> pages 1 AND 2, bytes 1 AND 6) with nand_default_block_markbad() if
> necessary, according to the flags marked in chip->options.
> 
> Note that I removed the line:
> 	ofs += mtd->oobsize;
> Unless I am wrong, this line was completely unnecessary in the
> first place.
> 
> Signed-off-by: Brian Norris <norris@broadcom.com>

Pushed to mtd-2.6.git / master, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

end of thread, other threads:[~2010-07-26  4:31 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-23 20:36 [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Brian Norris
2010-06-25 21:36 ` [PATCH 2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
2010-07-13  8:21   ` Artem Bityutskiy
2010-07-13 22:12     ` [PATCH v2 0/2] Improved BB Scanning Brian Norris
2010-07-13 22:13       ` [PATCH v2 1/2] mtd/nand, BB detect: factory marker in page 1, 2, last and byte 1 or 6 Brian Norris
2010-07-13 22:13       ` [PATCH v2 2/2] mtd/nand: More BB Detection, dynamic scan options Brian Norris
2010-07-13 23:56         ` Brian Norris
2010-07-15 19:15           ` [PATCH v3 " Brian Norris
2010-07-18 16:38       ` [PATCH v2 0/2] Improved BB Scanning Artem Bityutskiy
2010-07-19 19:32         ` Brian Norris
2010-07-21  9:49           ` Artem Bityutskiy
2010-07-22 19:44             ` Karl Beldan
2010-07-21 23:53       ` [PATCH] mtd/nand: Update nand_default_block_markbad() Brian Norris
2010-07-26  4:30         ` Artem Bityutskiy
2010-07-08  9:15 ` [PATCH] mtd/nand: Edit macro flag for BBT scan of last page in block Artem Bityutskiy
2010-07-13  8:01 ` Artem Bityutskiy

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.