[PATCH 5/6] nand: big BBT overhaul

2015-04-15 Thread peterpandong
Not complete. Need to actually allocate and initialize struct nand_bbt.

TBD: should struct nand_bbt be embedded in mtd_info? Might help provide
some automatic routine registration.

Signed-off-by: Brian Norris 
Signed-off-by: Peter Pan 
---
 drivers/mtd/nand/docg4.c |   3 +-
 drivers/mtd/nand/nand_base.c |  53 +++--
 drivers/mtd/nand/nand_bbt.c  | 513 +--
 include/linux/mtd/bbm.h  |  44 +---
 include/linux/mtd/nand.h |   4 +-
 include/linux/mtd/nand_bbt.h | 160 ++
 6 files changed, 406 insertions(+), 371 deletions(-)
 create mode 100644 include/linux/mtd/nand_bbt.h

diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index e5d7bca..9b671b9 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1064,8 +1064,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
unsigned long bits = ~buf[i];
for_each_set_bit(bitnum, , 8) {
int badblock = block + 7 - bitnum;
-   nand->bbt[badblock / 4] |=
-   0x03 << ((badblock % 4) * 2);
+   nand_bbt_markbad(nand->nand_bbt, badblock << 
nand->bbt_erase_shift);
mtd->ecc_stats.badblocks++;
dev_notice(doc->dev, "factory-marked bad block: %d\n",
   badblock);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index df7eb4f..ff9db05 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -98,6 +98,9 @@ static int nand_get_device(struct mtd_info *mtd, int 
new_state);
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 struct mtd_oob_ops *ops);
 
+static int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+  int allowbbt);
+
 /*
  * For devices which display every fart in the system on a separate LED. Is
  * compiled away when LED support is disabled.
@@ -451,8 +454,8 @@ static int nand_block_markbad_lowlevel(struct mtd_info 
*mtd, loff_t ofs)
}
 
/* Mark block bad in BBT */
-   if (chip->bbt) {
-   res = nand_markbad_bbt(mtd, ofs);
+   if (chip->nand_bbt) {
+   res = nand_bbt_markbad(chip->nand_bbt, ofs);
if (!ret)
ret = res;
}
@@ -494,10 +497,10 @@ static int nand_block_isreserved(struct mtd_info *mtd, 
loff_t ofs)
 {
struct nand_chip *chip = mtd->priv;
 
-   if (!chip->bbt)
+   if (!chip->nand_bbt)
return 0;
/* Return info from the table */
-   return nand_isreserved_bbt(mtd, ofs);
+   return nand_bbt_isreserved(chip->nand_bbt, ofs);
 }
 
 /**
@@ -514,12 +517,25 @@ static int nand_block_checkbad(struct mtd_info *mtd, 
loff_t ofs, int getchip,
   int allowbbt)
 {
struct nand_chip *chip = mtd->priv;
+   struct nand_bbt *bbt = chip->nand_bbt;
 
-   if (!chip->bbt)
+   if (!bbt)
return chip->block_bad(mtd, ofs, getchip);
 
/* Return info from the table */
-   return nand_isbad_bbt(mtd, ofs, allowbbt);
+   if (nand_bbt_isbad(bbt, ofs))
+   return 1;
+   else if (allowbbt)
+   return 0;
+   else
+   return nand_bbt_isreserved(bbt, ofs);
+}
+
+static int nand_default_bbt(struct mtd_info *mtd)
+{
+   struct nand_chip *chip = mtd->priv;
+
+   return nand_bbt_init(chip->nand_bbt);
 }
 
 /**
@@ -2711,7 +2727,7 @@ static int nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
  *
  * Erase one ore more blocks.
  */
-int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+static int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt)
 {
int page, status, pages_per_block, ret, chipnr;
@@ -2818,6 +2834,20 @@ erase_exit:
return ret;
 }
 
+/* NAND BBT helper - erase a block, including reserved blocks */
+static int nand_bbt_erase_block(struct mtd_info *mtd, loff_t addr)
+{
+   struct erase_info einfo;
+   struct nand_chip *chip = mtd->priv;
+
+   memset(, 0, sizeof(einfo));
+   einfo.mtd = mtd;
+   einfo.addr = addr;
+   einfo.len = 1ULL << chip->phys_erase_shift;
+
+   return nand_erase_nand(mtd, , 1);
+}
+
 /**
  * nand_sync - [MTD Interface] sync
  * @mtd: MTD device structure
@@ -4236,14 +4266,11 @@ void nand_release(struct mtd_info *mtd)
mtd_device_unregister(mtd);
 
/* Free bad block table memory */
-   kfree(chip->bbt);
+   if (chip->nand_bbt)
+   nand_bbt_release(chip->nand_bbt);
+   kfree(chip->nand_bbt);
if (!(chip->options & NAND_OWN_BUFFERS))
kfree(chip->buffers);
-
-   /* Free bad block descriptor memory */
-   if (chip->badblock_pattern && chip->badblock_pattern->options
-   & 

[PATCH 5/6] nand: big BBT overhaul

2015-04-15 Thread peterpandong
Not complete. Need to actually allocate and initialize struct nand_bbt.

TBD: should struct nand_bbt be embedded in mtd_info? Might help provide
some automatic routine registration.

Signed-off-by: Brian Norris computersforpe...@gmail.com
Signed-off-by: Peter Pan peterpand...@micron.com
---
 drivers/mtd/nand/docg4.c |   3 +-
 drivers/mtd/nand/nand_base.c |  53 +++--
 drivers/mtd/nand/nand_bbt.c  | 513 +--
 include/linux/mtd/bbm.h  |  44 +---
 include/linux/mtd/nand.h |   4 +-
 include/linux/mtd/nand_bbt.h | 160 ++
 6 files changed, 406 insertions(+), 371 deletions(-)
 create mode 100644 include/linux/mtd/nand_bbt.h

diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index e5d7bca..9b671b9 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1064,8 +1064,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
unsigned long bits = ~buf[i];
for_each_set_bit(bitnum, bits, 8) {
int badblock = block + 7 - bitnum;
-   nand-bbt[badblock / 4] |=
-   0x03  ((badblock % 4) * 2);
+   nand_bbt_markbad(nand-nand_bbt, badblock  
nand-bbt_erase_shift);
mtd-ecc_stats.badblocks++;
dev_notice(doc-dev, factory-marked bad block: %d\n,
   badblock);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index df7eb4f..ff9db05 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -98,6 +98,9 @@ static int nand_get_device(struct mtd_info *mtd, int 
new_state);
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 struct mtd_oob_ops *ops);
 
+static int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+  int allowbbt);
+
 /*
  * For devices which display every fart in the system on a separate LED. Is
  * compiled away when LED support is disabled.
@@ -451,8 +454,8 @@ static int nand_block_markbad_lowlevel(struct mtd_info 
*mtd, loff_t ofs)
}
 
/* Mark block bad in BBT */
-   if (chip-bbt) {
-   res = nand_markbad_bbt(mtd, ofs);
+   if (chip-nand_bbt) {
+   res = nand_bbt_markbad(chip-nand_bbt, ofs);
if (!ret)
ret = res;
}
@@ -494,10 +497,10 @@ static int nand_block_isreserved(struct mtd_info *mtd, 
loff_t ofs)
 {
struct nand_chip *chip = mtd-priv;
 
-   if (!chip-bbt)
+   if (!chip-nand_bbt)
return 0;
/* Return info from the table */
-   return nand_isreserved_bbt(mtd, ofs);
+   return nand_bbt_isreserved(chip-nand_bbt, ofs);
 }
 
 /**
@@ -514,12 +517,25 @@ static int nand_block_checkbad(struct mtd_info *mtd, 
loff_t ofs, int getchip,
   int allowbbt)
 {
struct nand_chip *chip = mtd-priv;
+   struct nand_bbt *bbt = chip-nand_bbt;
 
-   if (!chip-bbt)
+   if (!bbt)
return chip-block_bad(mtd, ofs, getchip);
 
/* Return info from the table */
-   return nand_isbad_bbt(mtd, ofs, allowbbt);
+   if (nand_bbt_isbad(bbt, ofs))
+   return 1;
+   else if (allowbbt)
+   return 0;
+   else
+   return nand_bbt_isreserved(bbt, ofs);
+}
+
+static int nand_default_bbt(struct mtd_info *mtd)
+{
+   struct nand_chip *chip = mtd-priv;
+
+   return nand_bbt_init(chip-nand_bbt);
 }
 
 /**
@@ -2711,7 +2727,7 @@ static int nand_erase(struct mtd_info *mtd, struct 
erase_info *instr)
  *
  * Erase one ore more blocks.
  */
-int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+static int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt)
 {
int page, status, pages_per_block, ret, chipnr;
@@ -2818,6 +2834,20 @@ erase_exit:
return ret;
 }
 
+/* NAND BBT helper - erase a block, including reserved blocks */
+static int nand_bbt_erase_block(struct mtd_info *mtd, loff_t addr)
+{
+   struct erase_info einfo;
+   struct nand_chip *chip = mtd-priv;
+
+   memset(einfo, 0, sizeof(einfo));
+   einfo.mtd = mtd;
+   einfo.addr = addr;
+   einfo.len = 1ULL  chip-phys_erase_shift;
+
+   return nand_erase_nand(mtd, einfo, 1);
+}
+
 /**
  * nand_sync - [MTD Interface] sync
  * @mtd: MTD device structure
@@ -4236,14 +4266,11 @@ void nand_release(struct mtd_info *mtd)
mtd_device_unregister(mtd);
 
/* Free bad block table memory */
-   kfree(chip-bbt);
+   if (chip-nand_bbt)
+   nand_bbt_release(chip-nand_bbt);
+   kfree(chip-nand_bbt);
if (!(chip-options  NAND_OWN_BUFFERS))
kfree(chip-buffers);
-
-   /* Free bad block descriptor memory */
-   if (chip-badblock_pattern  chip-badblock_pattern-options
-