[PATCH v2 05/12] mtd: nand: use new BBT API instead of old ones
Peter Pan
peterpansjtu at gmail.com
Wed Jan 6 22:03:23 PST 2016
On Wed, Jan 6, 2016 at 11:22 PM, Boris Brezillon
<boris.brezillon at free-electrons.com> wrote:
> On Tue, 15 Dec 2015 05:59:31 +0000
> Peter Pan <peterpansjtu at gmail.com> wrote:
>
>> From: Brian Norris <computersforpeace at gmail.com>
>>
>> Use new BBT APIs (nand_bbt_*()) in NAND. Keep old APIs (nand_*_bbt())
>> exist temporarily.
>>
>> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
>> [Peter: 1. use nand_bbt_markbad_factory() in docg4.c and implement
>> 2. nand_create_factory_badblock_pattern(), nand_is_bad_bbm() and
>> nand_default_bbt() in nand_base.c
>> 3. add NAND_BADBLOCK_PATTERN_ALLOC macro]
>> Signed-off-by: Peter Pan <peterpandong at micron.com>
>> ---
>> drivers/mtd/nand/docg4.c | 6 +-
>> drivers/mtd/nand/nand_base.c | 140 ++++++++++++++++++++++++++++++++++++++++---
>> include/linux/mtd/nand.h | 9 ++-
>> 3 files changed, 143 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
>> index da93d7f..1be7fa2 100644
>> --- a/drivers/mtd/nand/docg4.c
>> +++ b/drivers/mtd/nand/docg4.c
>> @@ -1037,7 +1037,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
>> * operation after device power-up. The above read ensures it never is.
>> * Ugly, I know.
>> */
>> - if (nand->bbt == NULL) /* no memory-based bbt */
>> + if (nand->nand_bbt == NULL) /* no memory-based bbt */
>> goto exit;
>>
>> if (mtd->ecc_stats.failed > eccfailed_stats) {
>> @@ -1064,8 +1064,8 @@ 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_factory(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 5aec154..28d7a58 100644
>> --- a/drivers/mtd/nand/nand_base.c
>> +++ b/drivers/mtd/nand/nand_base.c
>
> [...]
>
>>
>> +/* 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;
>
> nand_chip backpointer is no longer stored in mtd->priv (nand_chip now
> embeds its own mtd_info field and we use the container_of trick to
> retrieve the nand_chip pointer from the mtd_info pointer).
>
> struct nand_chip *chip = mtd_to_nand(mtd);
>
Fix this in v3.
>> +
>> + 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);
>> +}
>> +
>
> [...]
>
>> +static int nand_is_bad_bbm(struct mtd_info *mtd, loff_t addr)
>> +{
>> + struct nand_chip *chip = mtd->priv;
>
> struct nand_chip *chip = mtd_to_nand(mtd);
Fix this in v3.
>
>> + struct mtd_oob_ops ops;
>> + struct nand_bbt_descr *bd = chip->badblock_pattern;
>> + int j, ret;
>> + int numpages;
>> +
>> + if (bd->options & NAND_BBT_SCAN2NDPAGE)
>> + numpages = 2;
>> + else
>> + numpages = 1;
>> +
>> + if (bd->options & NAND_BBT_SCANLASTPAGE)
>> + addr += mtd->erasesize - (mtd->writesize * numpages);
>> +
>> + ops.ooblen = mtd->oobsize;
>> + ops.oobbuf = chip->buffers->databuf;
>> + ops.ooboffs = 0;
>> + ops.datbuf = NULL;
>> + ops.mode = MTD_OPS_PLACE_OOB;
>> +
>> + for (j = 0; j < numpages; j++) {
>> + /*
>> + * Read the full oob until read_oob is fixed to handle single
>> + * byte reads for 16 bit buswidth.
>> + */
>> + ret = nand_do_read_oob(mtd, addr, &ops);
>> + /* Ignore ECC errors when checking for BBM */
>> + if (ret && !mtd_is_bitflip_or_eccerr(ret))
>> + return ret;
>> +
>> + if (memcmp(chip->buffers->databuf + bd->offs,
>> + bd->pattern, bd->len))
>> + return 1;
>> +
>> + addr += mtd->writesize;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int nand_default_bbt(struct mtd_info *mtd)
>> +{
>> + struct nand_chip *chip = mtd->priv;
>
> struct nand_chip *chip = mtd_to_nand(mtd);
Fix this in v3.
>
>> + struct nand_bbt *bbt = kzalloc(sizeof(struct nand_bbt), GFP_KERNEL);
>> +
>> + if (!bbt)
>> + return -ENOMEM;
>> +
>> + bbt->bbt_options = chip->bbt_options;
>> + bbt->mtd = mtd;
>> + bbt->numchips = chip->numchips;
>> + bbt->chipsize = chip->chipsize;
>> + bbt->chip_shift = chip->chip_shift;
>> + bbt->bbt_erase_shift = chip->phys_erase_shift;
>> + bbt->page_shift = chip->page_shift;
>> + bbt->bbt_td = chip->bbt_td;
>> + bbt->bbt_md = chip->bbt_md;
>> + bbt->is_bad_bbm = nand_is_bad_bbm;
>> + bbt->erase = nand_bbt_erase_block;
>> + chip->nand_bbt = bbt;
>> +
>> + if (!chip->badblock_pattern &&
>> + nand_create_factory_badblock_pattern(chip))
>> + return -ENOMEM;
>> +
>> + return nand_bbt_init(chip->nand_bbt);
>> +}
>
>
>
> --
> Boris Brezillon, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
Thanks
Peter Pan
More information about the linux-mtd
mailing list