From: Brian Norris <computersforpe...@gmail.com> Since NAND already create its nand_bbt struct, we can use erase() hook instead of call nand_erase_nand() directly. Also, we can use is_bad_bbm() to avoid passing badblock_pattern to BBT.
Signed-off-by: Brian Norris <computersforpe...@gmail.com> [Peter: remove @buf in create_bbt()] Signed-off-by: Peter Pan <peterpand...@micron.com> --- drivers/mtd/nand/nand_bbt.c | 138 ++++---------------------------------------- 1 file changed, 12 insertions(+), 126 deletions(-) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index f256be1..a5c8ab5 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -122,23 +122,6 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc } /** - * check_short_pattern - [GENERIC] check if a pattern is in the buffer - * @buf: the buffer to search - * @td: search pattern descriptor - * - * Check for a pattern at the given place. Used to search bad block tables and - * good / bad block identifiers. Same as check_pattern, but no optional empty - * check. - */ -static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) -{ - /* Compare the pattern */ - if (memcmp(buf + td->offs, td->pattern, td->len)) - return -1; - return 0; -} - -/** * add_marker_len - compute the length of the marker in data area * @td: BBT descriptor used for computation * @@ -409,63 +392,23 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, } } -/* Scan a given block partially */ -static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, - loff_t offs, uint8_t *buf, int numpages) -{ - struct mtd_oob_ops ops; - int j, ret; - - ops.ooblen = mtd->oobsize; - ops.oobbuf = buf; - 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 = mtd_read_oob(mtd, offs, &ops); - /* Ignore ECC errors when checking for BBM */ - if (ret && !mtd_is_bitflip_or_eccerr(ret)) - return ret; - - if (check_short_pattern(buf, bd)) - return 1; - - offs += mtd->writesize; - } - return 0; -} - /** * create_bbt - [GENERIC] Create a bad block table by scanning the device * @mtd: MTD device structure - * @buf: temporary buffer - * @bd: descriptor for the good/bad block search pattern * @chip: create the table for a specific chip, -1 read all chips; applies only * if NAND_BBT_PERCHIP option is set * * Create a bad block table by scanning the device for the given good/bad block * identify pattern. */ -static int create_bbt(struct mtd_info *mtd, uint8_t *buf, - struct nand_bbt_descr *bd, int chip) +static int create_bbt(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd_to_nand(mtd); - int i, numblocks, numpages; - int startblock; + int i, startblock, numblocks; loff_t from; pr_info("Scanning device for bad blocks\n"); - if (bd->options & NAND_BBT_SCAN2NDPAGE) - numpages = 2; - else - numpages = 1; - if (chip == -1) { numblocks = mtd->size >> this->bbt_erase_shift; startblock = 0; @@ -482,15 +425,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, from = (loff_t)startblock << this->bbt_erase_shift; } - if (this->bbt_options & NAND_BBT_SCANLASTPAGE) - 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(mtd, bd, from, buf, numpages); + ret = this->nand_bbt->is_bad_bbm(mtd, from); if (ret < 0) return ret; @@ -619,7 +557,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, int chipsel) { struct nand_chip *this = mtd_to_nand(mtd); - struct erase_info einfo; int i, res, chip = 0; int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; int nrchips, pageoffs, ooboffs; @@ -782,11 +719,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt); } - memset(&einfo, 0, sizeof(einfo)); - einfo.mtd = mtd; - einfo.addr = to; - einfo.len = 1 << this->bbt_erase_shift; - res = nand_erase_nand(mtd, &einfo, 1); + res = this->nand_bbt->erase(mtd, to); if (res < 0) goto outerr; @@ -812,30 +745,26 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, /** * nand_memory_bbt - [GENERIC] create a memory based bad block table * @mtd: MTD device structure - * @bd: descriptor for the good/bad block search pattern * * The function creates a memory based bbt by scanning the device for * manufacturer / software marked good / bad blocks. */ -static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +static inline int nand_memory_bbt(struct mtd_info *mtd) { - struct nand_chip *this = mtd_to_nand(mtd); - - return create_bbt(mtd, this->buffers->databuf, bd, -1); + return create_bbt(mtd, -1); } /** * check_create - [GENERIC] create and write bbt(s) if necessary * @mtd: MTD device structure * @buf: temporary buffer - * @bd: descriptor for the good/bad block search pattern * * The function checks the results of the previous call to read_bbt and creates * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found * for the chip/device. Update is necessary if one of the tables is missing or * the version nr. of one table is less than the other. */ -static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) +static int check_create(struct mtd_info *mtd, uint8_t *buf) { int i, chips, writeops, create, chipsel, res, res2; struct nand_chip *this = mtd_to_nand(mtd); @@ -895,7 +824,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc /* Create the table in memory by scanning the chip(s) */ if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY)) - create_bbt(mtd, buf, bd, chipsel); + create_bbt(mtd, chipsel); td->version[i] = 1; if (md) @@ -1063,7 +992,6 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) /** * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) * @mtd: MTD device structure - * @bd: descriptor for the good/bad block search pattern * * The function checks, if a bad block table(s) is/are already available. If * not it scans the device for manufacturer marked good / bad blocks and writes @@ -1072,7 +1000,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) * The bad block table memory is allocated here. It must be freed by calling * the nand_free_bbt function. */ -static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +static int nand_scan_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); int len, res; @@ -1094,7 +1022,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) * memory based bad block table. */ if (!td) { - if ((res = nand_memory_bbt(mtd, bd))) { + if ((res = nand_memory_bbt(mtd))) { pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); goto err; } @@ -1120,7 +1048,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) search_read_bbts(mtd, buf, td, md); } - res = check_create(mtd, buf, bd); + res = check_create(mtd, buf); if (res) goto err; @@ -1193,12 +1121,6 @@ static int nand_update_bbt(struct mtd_info *mtd, loff_t offs) return res; } -/* - * Define some generic bad / good block scan pattern which are used - * while scanning a device for factory marked good / bad blocks. - */ -static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; - /* Generic flash bbt descriptors */ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; @@ -1243,35 +1165,6 @@ static struct nand_bbt_descr bbt_mirror_no_oob_descr = { .pattern = mirror_pattern }; -#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB) -/** - * nand_create_badblock_pattern - [INTERN] 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. - */ -static int nand_create_badblock_pattern(struct nand_chip *this) -{ - struct nand_bbt_descr *bd; - if (this->badblock_pattern) { - pr_warn("Bad block pattern already allocated; not replacing\n"); - return -EINVAL; - } - bd = kzalloc(sizeof(*bd), GFP_KERNEL); - if (!bd) - return -ENOMEM; - bd->options = this->bbt_options & BADBLOCK_SCAN_MASK; - 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 @@ -1282,7 +1175,6 @@ static int nand_create_badblock_pattern(struct nand_chip *this) int nand_default_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - int ret; /* Is a flash based bad block table requested? */ if (this->bbt_options & NAND_BBT_USE_FLASH) { @@ -1301,13 +1193,7 @@ int nand_default_bbt(struct mtd_info *mtd) this->bbt_md = NULL; } - if (!this->badblock_pattern) { - ret = nand_create_badblock_pattern(this); - if (ret) - return ret; - } - - return nand_scan_bbt(mtd, this->badblock_pattern); + return nand_scan_bbt(mtd); } /** -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/