nand坏块管理代码跟踪

Arch/arm/mach-s3c2410/mach-smdk2410.c

static int chip0_map[] = { 0 };

硬件信息

static struct mtd_partitionsmdk_default_nand_part[] = {

 

       [0] = {

                .name   = "boot",

                .size   = SZ_128K + SZ_64K,

                .offset = 0,

       },

       [1] = {

                .name   = "kernel",

                .size   = SZ_2M - SZ_128K - SZ_64K,

                .offset = SZ_128K + SZ_64K,

       },

       [2] = {

                .name   = "rootfs",

                .size   = 62 * SZ_1M,

                .offset = SZ_2M,

       }

};

static struct s3c2410_nand_setsmdk_nand_sets[] = {

       [0] = {

                .name           = "chip0",

                .nr_chips       = 1,

                .nr_map         = chip0_map,

                .nr_partitions  = ARRAY_SIZE(smdk_default_nand_part),

                .partitions     = smdk_default_nand_part

       },

 

};

 

static void smdk_nand_select(structs3c2410_nand_set *set, int slot)

{

 

       slot = set->nr_map[slot] & 3;

 

}

 

static struct s3c2410_platform_nandsmdk_nand_info = {

       .tacls          = 0,//80,

       .twrph0         = 20,//80,

       .twrph1         = 0,//80,

       .nr_sets        =ARRAY_SIZE(smdk_nand_sets),

       .sets           = smdk_nand_sets,

       .select_chip    =smdk_nand_select,

};

 

drivers/mtd/nand/s3c2410.c

static int s3c2410_nand_probe(struct device*dev)

{

         …

      for (setno = 0; setno < nr_sets; setno++, nmtd++) {

                pr_debug("initialising set%d (%p, info %p)\n",

                         setno, nmtd, info);

 

                s3c2410_nand_init_chip(info,nmtd, sets);

 

                nmtd->scan_res =nand_scan(&nmtd->mtd,

                                          (sets) ? sets->nr_chips : 1);

 

                if (nmtd->scan_res == 0) {

                       s3c2410_nand_add_partition(info, nmtd, sets);

                }

 

                if (sets != NULL)

                        sets++;

       }

  …

}

drivers/mtd/nand/s3c2410.c

static void s3c2410_nand_init_chip(structs3c2410_nand_info *info,

                                   structs3c2410_nand_mtd *nmtd,

                                   structs3c2410_nand_set *set)

{

       struct nand_chip *chip = &nmtd->chip;

 

       chip->IO_ADDR_R    = (char*)info->regs + S3C2410_NFDATA;

       chip->IO_ADDR_W    = (char*)info->regs + S3C2410_NFDATA;

       chip->hwcontrol    =s3c2410_nand_hwcontrol;

       chip->dev_ready    =s3c2410_nand_devready;

       chip->cmdfunc      =s3c2410_nand_command;

       chip->write_buf    =s3c2410_nand_write_buf;

       chip->read_buf     =s3c2410_nand_read_buf;

       chip->select_chip  =s3c2410_nand_select_chip;

       chip->chip_delay   = 50;

       chip->priv         = nmtd;

       chip->options      = 0;

       chip->controller   =&info->controller;

 

       nmtd->info         = info;

       nmtd->mtd.priv     = chip;

       nmtd->set          = set;

 

       if (hardware_ecc) {

                chip->correct_data  = s3c2410_nand_correct_data;

                chip->enable_hwecc  = s3c2410_nand_enable_hwecc;

                chip->calculate_ecc =s3c2410_nand_calculate_ecc;

                chip->eccmode       = NAND_ECC_HW3_512;

                chip->autooob       = &nand_hw_eccoob;

        } else {

       //---------modify by liyutai-----------------//

       //      chip->eccmode       = NAND_ECC_SOFT;

                chip->eccmode       = NAND_ECC_NONE;

       //-------------------------------------------//

       }

}

 

Drivers/mtd/nand/nand_ids.c

struct nand_flash_dev {

       char *name;

       int id;

       unsigned long pagesize;

       unsigned long chipsize;

       unsigned long erasesize;

       unsigned long options;

};

struct nand_flash_dev nand_flash_ids[] = {

{"NAND 64MiB 3,3V 8-bit",       0x76, 512, 64, 0x4000, 0},

}

 

static struct nand_oobinfo nand_oob_16 = {

       .useecc = MTD_NANDECC_AUTOPLACE,

       .eccbytes = 6,

       .eccpos = {0, 1, 2, 3, 6, 7},

       .oobfree = { {8, 8} }

};

 

drivers/mtd/nand/nand_base.c

int nand_scan (struct mtd_info *mtd, intmaxchips)

{

 …

       if (!this->select_chip)

                this->select_chip =nand_select_chip;

       if (!this->write_byte)

                this->write_byte = busw ?nand_write_byte16 : nand_write_byte;

       if (!this->read_byte)

                this->read_byte = busw ?nand_read_byte16 : nand_read_byte;

       if (!this->write_word)

                this->write_word =nand_write_word;

       if (!this->read_word)

                this->read_word =nand_read_word;

       if (!this->block_bad)

                this->block_bad =nand_block_bad;

       if (!this->block_markbad)

                this->block_markbad =nand_default_block_markbad;

       if (!this->write_buf)

                this->write_buf = busw ?nand_write_buf16 : nand_write_buf;

       if (!this->read_buf)

                this->read_buf = busw ?nand_read_buf16 : nand_read_buf;

       if (!this->verify_buf)

                this->verify_buf = busw ?nand_verify_buf16 : nand_verify_buf;

       if (!this->scan_bbt)

                this->scan_bbt =nand_default_bbt;

                if (!mtd->name) mtd->name= nand_flash_ids[i].name;

                this->chipsize =nand_flash_ids[i].chipsize << 20;

 

         mtd->erasesize =nand_flash_ids[i].erasesize;     //0x4000

                        mtd->oobblock =nand_flash_ids[i].pagesize;    //512

                        mtd->oobsize =mtd->oobblock / 32;                          //16

                        busw =nand_flash_ids[i].options & NAND_BUSWIDTH_16;  //0

               /* Calculate the address shiftfrom the page size */

                this->page_shift =ffs(mtd->oobblock) - 1;  //9

                this->bbt_erase_shift =this->phys_erase_shift = ffs(mtd->erasesize) - 1; //15

                this->chip_shift =ffs(this->chipsize) - 1;   //26

 

                /* Set the bad block position*/

                this->badblockpos =mtd->oobblock > 512 ?

                        NAND_LARGE_BADBLOCK_POS: NAND_SMALL_BADBLOCK_POS;    // NAND_SMALL_BADBLOCK_POS  5

 

                /* Get chip options, preservenon chip based options */

                this->options &=~NAND_CHIPOPTIONS_MSK;

                this->options |=nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;

                /* Set this as a default. Boarddrivers can override it, if neccecary */

                this->options |=NAND_NO_AUTOINCR;

 

this->erase_cmd= single_erase_cmd;

 

        /* Allocate buffers, if neccecary */

        if (!this->oob_buf) {

                size_t len;

                len = mtd->oobsize <<(this->phys_erase_shift - this->page_shift); //512

                this->oob_buf = kmalloc(len, GFP_KERNEL);

                if (!this->oob_buf) {

                        printk (KERN_ERR"nand_scan(): Cannot allocate oob_buf\n");

                        return -ENOMEM;

                }

                this->options |=NAND_OOBBUF_ALLOC;

        }

 

        if (!this->data_buf) {

                size_t len;

                len = mtd->oobblock +mtd->oobsize; //512+16

                this->data_buf = kmalloc(len, GFP_KERNEL);

                if (!this->data_buf) {

                        if (this->options& NAND_OOBBUF_ALLOC)

                                kfree(this->oob_buf);

                        printk (KERN_ERR"nand_scan(): Cannot allocate data_buf\n");

                        return -ENOMEM;

                }

                this->options |=NAND_DATABUF_ALLOC;

        }

        /* Store the number of chips and calctotal size for mtd */

        this->numchips = i;

        mtd->size = i * this->chipsize;

        /* Convert chipsize to number of pagesper chip -1. */

        this->pagemask = (this->chipsize>> this->page_shift) - 1; //0x1ffff

        /* Preset the internal oob buffer */

        memset(this->oob_buf, 0xff,mtd->oobsize << (this->phys_erase_shift - this->page_shift));

this->autooob= &nand_oob_16;

mtd->oobavail= mtd->oobsize - (this->autooob->eccbytes + 1);             //9

        this->eccsize = 256;    /* set default eccsize */

        this->eccbytes = 3;

this->eccmode= NAND_ECC_NONE;

mtd->eccsize= this->eccsize;

this->eccsteps= 1;

        /* Fill in remaining MTD driver data */

        mtd->type = MTD_NANDFLASH;

        mtd->flags = MTD_CAP_NANDFLASH |MTD_ECC;

        mtd->ecctype = MTD_ECC_SW;

        mtd->erase = nand_erase;

        mtd->point = NULL;

        mtd->unpoint = NULL;

        mtd->read = nand_read;

        mtd->write = nand_write;

        mtd->read_ecc = nand_read_ecc;

        mtd->write_ecc = nand_write_ecc;

        mtd->read_oob = nand_read_oob;

        mtd->write_oob = nand_write_oob;

        mtd->readv = NULL;

        mtd->writev = nand_writev;

        mtd->writev_ecc = nand_writev_ecc;

        mtd->sync = nand_sync;

        mtd->lock = NULL;

        mtd->unlock = NULL;

        mtd->suspend = NULL;

        mtd->resume = NULL;

        mtd->block_isbad = nand_block_isbad;

        mtd->block_markbad =nand_block_markbad;

 

        /* and make the autooob the default one*/

        memcpy(&mtd->oobinfo, this->autooob,sizeof(mtd->oobinfo));

 

        mtd->owner = THIS_MODULE;

 

        /* Build bad block table */

        return this->scan_bbt (mtd);

}

 

drivers/mtd/nand/nand_bbt.c

static uint8_t scan_ff_pattern[] = { 0xff,0xff };

 

static struct nand_bbt_descr smallpage_memorybased= {

       .options = 0,

       .offs = 5,

       .len = 1,

       .pattern = scan_ff_pattern

};

int nand_default_bbt (struct mtd_info *mtd)

{

                   …

       /* Is a flash based bad block table requested ? */

       if (this->options & NAND_USE_FLASH_BBT) {

                /* Use the default patterndescriptors */

                if (!this->bbt_td) {

                        this->bbt_td =&bbt_main_descr;

                        this->bbt_md =&bbt_mirror_descr;

                }

                if (!this->badblock_pattern){

                       this->badblock_pattern = (mtd->oobblock > 512) ?

                               &largepage_flashbased : &smallpage_flashbased;

                }

       } else {

                this->bbt_td = NULL;

                this->bbt_md = NULL;

                if (!this->badblock_pattern){

                       this->badblock_pattern = (mtd->oobblock > 512) ?

                               &largepage_memorybased : &smallpage_memorybased; // smallpage_memorybased

                }

       }

       return nand_scan_bbt (mtd, this->badblock_pattern);

}

 

int nand_scan_bbt (struct mtd_info *mtd,struct nand_bbt_descr *bd)

{

                   …

      struct nand_bbt_descr *td = this->bbt_td;

       struct nand_bbt_descr *md = this->bbt_md;

       len = mtd->size >> (this->bbt_erase_shift + 2);       //64M >> 17 = 512

       /* Allocate memory (2bit per block) */

       this->bbt = kmalloc (len, GFP_KERNEL);

       if (!this->bbt) {

                printk (KERN_ERR"nand_scan_bbt: Out of memory\n");

                return -ENOMEM;

       }

       /* Clear the memory bad block table */

       memset (this->bbt, 0x00, len);

 

       /* If no primary table decriptor is given, scan the device

        * to build a memory based bad block table

        */

       if (!td)

                return nand_memory_bbt(mtd,bd);

}

 

static int nand_memory_bbt (struct mtd_info*mtd, struct nand_bbt_descr *bd)

{

       struct nand_chip *this = mtd->priv;

 

       /* Ensure that we only scan for the pattern and nothing else */

       bd->options = 0;

       create_bbt (mtd, this->data_buf, bd, -1);

       return 0;

}

 

static void create_bbt (struct mtd_info*mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)

{

         …

                 if (bd->options &NAND_BBT_SCANALLPAGES)

                len = 1 <<(this->bbt_erase_shift - this->page_shift);

       else {

                if (bd->options &NAND_BBT_SCAN2NDPAGE)

                        len = 2;

                else

                        len = 1;     //here

       }

       scanlen = mtd->oobblock + mtd->oobsize;  //512 + 16 = 528

       readlen = len * mtd->oobblock; //512

       ooblen = len * mtd->oobsize;           //16

 

       if (chip == -1) {

                /* Note that numblocks is 2 *(real numblocks) here, see i+=2 below as it

                 * makes shifting and maskingless painful */

                numblocks = mtd->size>> (this->bbt_erase_shift - 1); //64M >> 14 = 4096

                startblock = 0;

               from = 0;

       }

                 for (i = startblock; i < numblocks;){

                nand_read_raw (mtd, buf, from,readlen, ooblen);

                for (j = 0; j < len; j++) {

                        if (check_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {

                                this->bbt[i>> 3] |= 0x03 << (i & 0x6);

                                printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",

                                        i>> 1, (unsigned int) from);

                               break;

                        }

                }

                i += 2;

                from += (1 <<this->bbt_erase_shift);

       }

}

 

Drivers/mtd/nand/nand_base.c

int nand_read_raw (struct mtd_info *mtd,uint8_t *buf, loff_t from, size_t len, size_t ooblen)

{

                 struct nand_chip *this = mtd->priv;

       int page = (int) (from >> this->page_shift);  //from >> 9

       int chip = (int) (from >> this->chip_shift); //from >> 26

       int sndcmd = 1;

       int cnt = 0;

       int pagesize = mtd->oobblock + mtd->oobsize; //512 + 16 = 528

       int     blockcheck = (1 <<(this->phys_erase_shift - this->page_shift)) - 1;          //63

 

                   …

                           /* Add requested oob length */

       len += ooblen;

 

       while (len) {

                if (sndcmd)

                        this->cmdfunc (mtd,NAND_CMD_READ0, 0, page & this->pagemask);

                sndcmd = 0;

 

                this->read_buf (mtd,&buf[cnt], pagesize);

 

                len -= pagesize;

                cnt += pagesize;

                page++;

 

                if (!this->dev_ready)

                        udelay(this->chip_delay);

                else

                        while(!this->dev_ready(mtd));

 

                /* Check, if the chip supportsauto page increment */

                if (!NAND_CANAUTOINCR(this) ||!(page & blockcheck))

                        sndcmd = 1;

       }

                   …

}

 

static int check_pattern (uint8_t *buf, intlen, int paglen, struct nand_bbt_descr *td)

{

       int i, end;

       uint8_t *p = buf;

 

       end = paglen + td->offs;

       if (td->options & NAND_BBT_SCANEMPTY) {

                for (i = 0; i < end; i++) {

                        if (p[i] != 0xff)

                                return -1;

                }

       }

       p += end;

 

       /* Compare the pattern */

       for (i = 0; i < td->len; i++) {

                if (p[i] != td->pattern[i])

                        return -1;

       }

 

       p += td->len;

       end += td->len;

       if (td->options & NAND_BBT_SCANEMPTY) {

                for (i = end; i < len; i++){

                        if (*p++ != 0xff)

                                return -1;

                }

       }

       return 0;

}

 

今天发现多了很多连续坏块,查文件系统没发现什么错误,查了很久,发现坏块扫描扫了整块NAND,报错的位置正好在kernel的位置,把kernel位置全部擦除,恢复正常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值