summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2016-08-15 19:22:01 -0400
committerBoris Brezillon <boris.brezillon@free-electrons.com>2016-09-23 03:35:16 -0400
commitc3baf278d3bf8d628df0b28aa4921c5457d40211 (patch)
tree114a342f131c90b268b03da8edd9dd3e70dffc2a /drivers/mtd
parent57d419a42c501713fd023bc21f8798c14ad4e005 (diff)
mtd: nand_bbt: Move BBT block selection logic out of write_bbt()
This clarifies the write_bbt() function by removing the write label and simplifying the error/exit path. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Tested-by: Kyle Roeschley <kyle.roeschley@ni.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/nand_bbt.c110
1 files changed, 74 insertions, 36 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 2fbb523df066..9fbd66482403 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -605,6 +605,69 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
605} 605}
606 606
607/** 607/**
608 * get_bbt_block - Get the first valid eraseblock suitable to store a BBT
609 * @this: the NAND device
610 * @td: the BBT description
611 * @md: the mirror BBT descriptor
612 * @chip: the CHIP selector
613 *
614 * This functions returns a positive block number pointing a valid eraseblock
615 * suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if
616 * all blocks are already used of marked bad. If td->pages[chip] was already
617 * pointing to a valid block we re-use it, otherwise we search for the next
618 * valid one.
619 */
620static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
621 struct nand_bbt_descr *md, int chip)
622{
623 int startblock, dir, page, numblocks, i;
624
625 /*
626 * There was already a version of the table, reuse the page. This
627 * applies for absolute placement too, as we have the page number in
628 * td->pages.
629 */
630 if (td->pages[chip] != -1)
631 return td->pages[chip] >>
632 (this->bbt_erase_shift - this->page_shift);
633
634 numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
635 if (!(td->options & NAND_BBT_PERCHIP))
636 numblocks *= this->numchips;
637
638 /*
639 * Automatic placement of the bad block table. Search direction
640 * top -> down?
641 */
642 if (td->options & NAND_BBT_LASTBLOCK) {
643 startblock = numblocks * (chip + 1) - 1;
644 dir = -1;
645 } else {
646 startblock = chip * numblocks;
647 dir = 1;
648 }
649
650 for (i = 0; i < td->maxblocks; i++) {
651 int block = startblock + dir * i;
652
653 /* Check, if the block is bad */
654 switch (bbt_get_entry(this, block)) {
655 case BBT_BLOCK_WORN:
656 case BBT_BLOCK_FACTORY_BAD:
657 continue;
658 }
659
660 page = block << (this->bbt_erase_shift - this->page_shift);
661
662 /* Check, if the block is used by the mirror table */
663 if (!md || md->pages[chip] != page)
664 return block;
665 }
666
667 return -ENOSPC;
668}
669
670/**
608 * write_bbt - [GENERIC] (Re)write the bad block table 671 * write_bbt - [GENERIC] (Re)write the bad block table
609 * @mtd: MTD device structure 672 * @mtd: MTD device structure
610 * @buf: temporary buffer 673 * @buf: temporary buffer
@@ -621,7 +684,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
621 struct nand_chip *this = mtd_to_nand(mtd); 684 struct nand_chip *this = mtd_to_nand(mtd);
622 struct erase_info einfo; 685 struct erase_info einfo;
623 int i, res, chip = 0; 686 int i, res, chip = 0;
624 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; 687 int bits, page, offs, numblocks, sft, sftmsk;
625 int nrchips, pageoffs, ooboffs; 688 int nrchips, pageoffs, ooboffs;
626 uint8_t msk[4]; 689 uint8_t msk[4];
627 uint8_t rcode = td->reserved_block_code; 690 uint8_t rcode = td->reserved_block_code;
@@ -653,45 +716,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
653 716
654 /* Loop through the chips */ 717 /* Loop through the chips */
655 for (; chip < nrchips; chip++) { 718 for (; chip < nrchips; chip++) {
656 /* 719 int block;
657 * There was already a version of the table, reuse the page 720
658 * This applies for absolute placement too, as we have the 721 block = get_bbt_block(this, td, md, chip);
659 * page nr. in td->pages. 722 if (block < 0) {
660 */ 723 pr_err("No space left to write bad block table\n");
661 if (td->pages[chip] != -1) { 724 res = block;
662 page = td->pages[chip]; 725 goto outerr;
663 goto write;
664 } 726 }
665 727
666 /* 728 /*
667 * Automatic placement of the bad block table. Search direction 729 * get_bbt_block() returns a block number, shift the value to
668 * top -> down? 730 * get a page number.
669 */ 731 */
670 if (td->options & NAND_BBT_LASTBLOCK) { 732 page = block << (this->bbt_erase_shift - this->page_shift);
671 startblock = numblocks * (chip + 1) - 1;
672 dir = -1;
673 } else {
674 startblock = chip * numblocks;
675 dir = 1;
676 }
677
678 for (i = 0; i < td->maxblocks; i++) {
679 int block = startblock + dir * i;
680 /* Check, if the block is bad */
681 switch (bbt_get_entry(this, block)) {
682 case BBT_BLOCK_WORN:
683 case BBT_BLOCK_FACTORY_BAD:
684 continue;
685 }
686 page = block <<
687 (this->bbt_erase_shift - this->page_shift);
688 /* Check, if the block is used by the mirror table */
689 if (!md || md->pages[chip] != page)
690 goto write;
691 }
692 pr_err("No space left to write bad block table\n");
693 return -ENOSPC;
694 write:
695 733
696 /* Set up shift count and masks for the flash table */ 734 /* Set up shift count and masks for the flash table */
697 bits = td->options & NAND_BBT_NRBITS_MSK; 735 bits = td->options & NAND_BBT_NRBITS_MSK;