[PATCH 5/6] nand: big BBT overhaul
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
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 -