MTD: spin_lock stuck problem about marking bad block for mtd driver [1/1]
authorxianjun.liu <xianjun.liu@amlogic.com>
Thu, 7 Mar 2019 09:26:42 +0000 (17:26 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 20 Mar 2019 06:53:17 +0000 (22:53 -0800)
PD#SWPL-5613

Problem:
boot fail because of the UBI write error

Solution:
fixed nested-calls spin-lock when update bbt

Verify:
AXG-S420

Change-Id: I56b603ebffa5557ab7949ead2fddd41323346d09
Signed-off-by: xianjun.liu <xianjun.liu@amlogic.com>
drivers/amlogic/mtd/aml_dtb.c
drivers/amlogic/mtd/aml_env.c
drivers/amlogic/mtd/aml_mtd.h
drivers/amlogic/mtd/aml_nand.c
drivers/amlogic/mtd/rsv_manage.c

index e8711d8..4259e15 100644 (file)
@@ -129,10 +129,12 @@ ssize_t dtb_read(struct file *file,
                loff_t *ppos)
 {
        u8 *dtb_ptr = NULL;
-       /*struct nand_flash *flash = &aml_chip_dtb->flash;*/
+       struct nand_chip *chip = &aml_chip_dtb->chip;
        struct mtd_info *mtd = aml_chip_dtb->mtd;
        ssize_t read_size = 0;
        int ret = 0;
+       loff_t addr;
+       int chipnr;
 
        if (*ppos == aml_chip_dtb->dtbsize)
                return 0;
@@ -146,8 +148,10 @@ ssize_t dtb_read(struct file *file,
        if (dtb_ptr == NULL)
                return -ENOMEM;
 
-       /*not need nand_get_device here, mtd->_read_xx will done with it*/
-       /*nand_get_device(mtd, FL_READING);*/
+       addr = *ppos;
+       nand_get_device(mtd, FL_READING);
+       chipnr = (int)(addr >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
        ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize);
        if (ret) {
                pr_info("%s: read failed:%d\n", __func__, ret);
@@ -163,8 +167,8 @@ ssize_t dtb_read(struct file *file,
        ret = copy_to_user(buf, (dtb_ptr + *ppos), read_size);
        *ppos += read_size;
 exit:
-       /*nand_release_device(mtd);*/
-       /* kfree(dtb_ptr); */
+       chip->select_chip(mtd, -1);
+       nand_release_device(mtd);
        vfree(dtb_ptr);
        return read_size;
 }
@@ -175,9 +179,11 @@ ssize_t dtb_write(struct file *file,
 {
        u8 *dtb_ptr = NULL;
        ssize_t write_size = 0;
-       /*struct nand_flash *flash = &aml_chip_dtb->flash;*/
-       struct mtd_info *mtd = aml_chip_dtb->mtd;
        int ret = 0;
+       struct nand_chip *chip = &aml_chip_dtb->chip;
+       struct mtd_info *mtd = aml_chip_dtb->mtd;
+       loff_t addr;
+       int chipnr;
 
        if (*ppos == aml_chip_dtb->dtbsize)
                return 0;
@@ -191,8 +197,10 @@ ssize_t dtb_write(struct file *file,
        if (dtb_ptr == NULL)
                return -ENOMEM;
 
-       /*not need nand_get_device here, mtd->_read_xx will done with it*/
-       /*nand_get_device(mtd, FL_WRITING);*/
+       addr = *ppos;
+       nand_get_device(mtd, FL_WRITING);
+       chipnr = (int)(addr >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
        ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize);
        if (ret) {
                pr_info("%s: read failed\n", __func__);
@@ -216,8 +224,8 @@ ssize_t dtb_write(struct file *file,
 
        *ppos += write_size;
 exit:
-       /*nand_release_device(mtd);*/
-       /* kfree(dtb_ptr); */
+       chip->select_chip(mtd, -1);
+       nand_release_device(mtd);
        vfree(dtb_ptr);
        return write_size;
 }
index 0de2242..c56fb11 100644 (file)
@@ -189,6 +189,10 @@ ssize_t uboot_env_read(struct file *file,
        u8 *env_ptr = NULL;
        ssize_t read_size = 0;
        int ret = 0;
+       struct nand_chip *chip = &aml_chip_env->chip;
+       struct mtd_info *mtd = aml_chip_env->mtd;
+       loff_t addr;
+       int chipnr;
 
        if (*ppos == CONFIG_ENV_SIZE)
                return 0;
@@ -201,7 +205,11 @@ ssize_t uboot_env_read(struct file *file,
        env_ptr = vmalloc(CONFIG_ENV_SIZE + 2048);
        if (env_ptr == NULL)
                return -ENOMEM;
-       mutex_lock(&env_mutex);
+
+       addr = *ppos;
+       nand_get_device(mtd, FL_READING);
+       chipnr = (int)(addr >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
 
        /*amlnand_get_device(aml_chip_env, CHIP_READING);*/
        ret = amlnf_env_read((u8 *)env_ptr, CONFIG_ENV_SIZE);
@@ -220,7 +228,8 @@ ssize_t uboot_env_read(struct file *file,
        ret = copy_to_user(buf, (env_ptr + *ppos), read_size);
        *ppos += read_size;
 exit:
-       mutex_unlock(&env_mutex);
+       chip->select_chip(mtd, -1);
+       nand_release_device(mtd);
        /*amlnand_release_device(aml_chip_env);*/
        vfree(env_ptr);
        return read_size;
@@ -233,6 +242,10 @@ ssize_t uboot_env_write(struct file *file,
        u8 *env_ptr = NULL;
        ssize_t write_size = 0;
        int ret = 0;
+       struct nand_chip *chip = &aml_chip_env->chip;
+       struct mtd_info *mtd = aml_chip_env->mtd;
+       loff_t addr;
+       int chipnr;
 
        if (*ppos == CONFIG_ENV_SIZE)
                return 0;
@@ -246,7 +259,10 @@ ssize_t uboot_env_write(struct file *file,
        if (env_ptr == NULL)
                return -ENOMEM;
 
-       mutex_lock(&env_mutex);
+       addr = *ppos;
+       nand_get_device(mtd, FL_WRITING);
+       chipnr = (int)(addr >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
 
        if ((*ppos + count) > CONFIG_ENV_SIZE)
                write_size = CONFIG_ENV_SIZE - *ppos;
@@ -264,7 +280,8 @@ ssize_t uboot_env_write(struct file *file,
 
        *ppos += write_size;
 exit:
-       mutex_unlock(&env_mutex);
+       chip->select_chip(mtd, -1);
+       nand_release_device(mtd);
        vfree(env_ptr);
        return write_size;
 }
index a8d475e..3d4cadf 100644 (file)
@@ -883,6 +883,9 @@ int boot_device_register(struct aml_nand_chip *aml_chip);
 int add_mtd_partitions(struct mtd_info *mtd,
        const struct mtd_partition *part, int num);
 
+int nand_get_device(struct mtd_info *mtd, int new_state);
+void nand_release_device(struct mtd_info *mtd);
+
 #ifdef AML_NAND_UBOOT
 extern int get_partition_from_dts(unsigned char *buffer);
 #endif
index 7251fff..e827a9a 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "aml_mtd.h"
 
-
 uint8_t nand_boot_flag;
 
 /*#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 13)*/
@@ -1913,9 +1912,10 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
        struct nand_chip *chip = mtd->priv;
        struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
-       struct mtd_oob_ops aml_oob_ops;
        int blk_addr, mtd_erase_shift;
        int8_t *buf = NULL;
+       int page, chipnr;
+       int ret = 0;
 
        if (!mtd->erasesize)
                return -EINVAL;
@@ -1935,19 +1935,18 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
        }
 mark_bad:
        /*no erase here, fixit*/
-       aml_oob_ops.mode = MTD_OPS_AUTO_OOB;
-       aml_oob_ops.len = mtd->writesize;
-       aml_oob_ops.ooblen = mtd->oobavail;
-       /*aml_oob_ops.ooboffs = chip->ecc.layout->oobfree[0].offset;*/
-       aml_oob_ops.ooboffs = 0;
-       aml_oob_ops.datbuf = chip->buffers->databuf;
-       aml_oob_ops.oobbuf = chip->oob_poi;
        chip->pagebuf = -1;
 
-       memset((unsigned char *)aml_oob_ops.datbuf, 0x0, mtd->writesize);
-       memset((unsigned char *)aml_oob_ops.oobbuf, 0x0, aml_oob_ops.ooblen);
-
-       return mtd->_write_oob(mtd, ofs, &aml_oob_ops);
+       memset((unsigned char *)chip->buffers->databuf, 0x0, mtd->writesize);
+       memset((unsigned char *)chip->oob_poi, 0x0, mtd->oobavail);
+       chipnr = (int)(ofs >> chip->chip_shift);
+       page = (int)(ofs >> chip->page_shift);
+       chip->select_chip(mtd, chipnr);
+       ret = chip->write_page(mtd, chip, 0, mtd->writesize,
+               chip->buffers->databuf,
+               1, page, 0, 0);
+       chip->select_chip(mtd, -1);
+       return ret;
 }
 
 static uint8_t aml_platform_read_byte(struct mtd_info *mtd)
@@ -2195,3 +2194,4 @@ exit_error:
        aml_chip->block_status = NULL;
        return err;
 }
+
index f0ddbc4..cb0de55 100644 (file)
@@ -418,9 +418,10 @@ int aml_nand_read_rsv_info(struct mtd_info *mtd,
        loff_t addr = 0;
        size_t amount_loaded = 0;
        size_t len;
-       struct mtd_oob_ops aml_oob_ops;
        unsigned char *data_buf;
        unsigned char oob_buf[sizeof(struct oobinfo_t)];
+       int page, realpage, chipnr;
+       struct nand_chip *chip = mtd_to_nand(mtd);
 
 READ_RSV_AGAIN:
        addr = nandrsv_info->valid_node->phy_blk_addr;
@@ -433,20 +434,19 @@ READ_RSV_AGAIN:
 
        oobinfo = (struct oobinfo_t *)oob_buf;
        while (amount_loaded < nandrsv_info->size) {
-               aml_oob_ops.mode = MTD_OPS_AUTO_OOB;
-               aml_oob_ops.len = mtd->writesize;
-               aml_oob_ops.ooblen = sizeof(struct oobinfo_t);
-               /*aml_oob_ops.ooboffs = mtd->ecclayout->oobfree[0].offset;*/
-               aml_oob_ops.ooboffs = 0;
-               aml_oob_ops.datbuf = data_buf;
-               aml_oob_ops.oobbuf = oob_buf;
-
-               memset((unsigned char *)aml_oob_ops.datbuf,
+               memset((unsigned char *)data_buf,
                        0x0, mtd->writesize);
-               memset((unsigned char *)aml_oob_ops.oobbuf,
-                       0x0, aml_oob_ops.ooblen);
-
-               error = mtd->_read_oob(mtd, addr, &aml_oob_ops);
+               memset((unsigned char *)oob_buf,
+                       0x0, sizeof(struct oobinfo_t));
+               chipnr = (int)(addr >> chip->chip_shift);
+               chip->select_chip(mtd, chipnr);
+               realpage = (int)(addr >> chip->page_shift);
+               page = realpage & chip->pagemask;
+
+               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+               error = chip->ecc.read_page(mtd, chip, data_buf,
+                                                         1, page);
+               chip->select_chip(mtd, -1);
                if ((error != 0) && (error != -EUCLEAN)) {
                        pr_info("blk good but read failed: %llx, %d\n",
                                (uint64_t)addr, error);
@@ -456,11 +456,12 @@ READ_RSV_AGAIN:
                        goto READ_RSV_AGAIN;
                }
 
+               memcpy(oob_buf, chip->oob_poi, mtd->oobavail);
                if (memcmp(oobinfo->name, nandrsv_info->name, 4))
                        pr_info("invalid nand info %s magic: %llx\n",
                                nandrsv_info->name, (uint64_t)addr);
-
                addr += mtd->writesize;
+               page++;
                len = min_t(uint32_t, mtd->writesize,
                        (nandrsv_info->size - amount_loaded));
                memcpy(buf + amount_loaded, data_buf, len);
@@ -487,8 +488,6 @@ READ_RSV_AGAIN:
                }
        }
 #endif
-       /* if(data_buf) */
-       /* kfree(data_buf); */
        return 0;
 }
 
@@ -544,18 +543,17 @@ static int aml_nand_write_rsv(struct mtd_info *mtd,
        struct aml_nandrsv_info_t *nandrsv_info, loff_t offset, u_char *buf)
 {
        struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
+       struct nand_chip *chip = mtd_to_nand(mtd);
        struct oobinfo_t *oobinfo;
        int error = 0;
        loff_t addr = 0;
        size_t amount_saved = 0;
        size_t len;
-       struct mtd_oob_ops aml_oob_ops;
        unsigned char *data_buf;
        unsigned char oob_buf[sizeof(struct oobinfo_t)];
+       int page, chipnr;
 
        data_buf = aml_chip->rsv_data_buf;
-       /* if (data_buf == NULL) */
-       /* return -ENOMEM; */
 
        addr = offset;
        pr_info("%s:%d,write info to %llx\n", __func__, __LINE__, addr);
@@ -584,21 +582,21 @@ static int aml_nand_write_rsv(struct mtd_info *mtd,
        }
 #endif
        while (amount_saved < nandrsv_info->size) {
-               aml_oob_ops.mode = MTD_OPS_AUTO_OOB;
-               aml_oob_ops.len = mtd->writesize;
-               aml_oob_ops.ooblen = sizeof(struct oobinfo_t);
-               aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/
-               aml_oob_ops.datbuf = data_buf;
-               aml_oob_ops.oobbuf = oob_buf;
-
-               memset((unsigned char *)aml_oob_ops.datbuf,
+               memset((unsigned char *)data_buf,
                        0x0, mtd->writesize);
                len = min_t(uint32_t, mtd->writesize,
                        nandrsv_info->size - amount_saved);
-               memcpy((unsigned char *)aml_oob_ops.datbuf,
+               memcpy((unsigned char *)data_buf,
                        buf + amount_saved, len);
 
-               error = mtd->_write_oob(mtd, addr, &aml_oob_ops);
+               page = (int)(addr >> chip->page_shift);
+               chipnr = (int)(addr >> chip->chip_shift);
+               memset(chip->oob_poi, 0xff, mtd->oobsize);
+               memcpy(chip->oob_poi, oob_buf, mtd->oobsize);
+               chip->select_chip(mtd, chipnr);
+               error = chip->write_page(mtd, chip, 0, len, data_buf,
+                       1, page, 0, 0);
+               chip->select_chip(mtd, -1);
                if (error) {
                        pr_info("blk check good but write failed: %llx, %d\n",
                                (uint64_t)addr, error);
@@ -609,17 +607,19 @@ static int aml_nand_write_rsv(struct mtd_info *mtd,
        }
        if (amount_saved < nandrsv_info->size)
                return 1;
-       /* kfree(data_buf); */
+
        return 0;
 }
 
 int aml_nand_save_rsv_info(struct mtd_info *mtd,
        struct aml_nandrsv_info_t *nandrsv_info, u_char *buf)
 {
+       struct nand_chip *chip = mtd_to_nand(mtd);
        struct free_node_t *free_node = NULL, *tmp_node = NULL;
        int error = 0, pages_per_blk, valid_page_addr, i = 1;
        loff_t addr = 0;
-       struct erase_info erase_info;
+       int chipnr = 0;
+       int page;
 
        pages_per_blk = mtd->erasesize / mtd->writesize;
        /*solve these abnormals caused by power off and ecc error*/
@@ -639,13 +639,12 @@ RE_SEARCH:
                        if ((valid_page_addr - i) == pages_per_blk) {
                                addr = nandrsv_info->valid_node->phy_blk_addr;
                                addr *= mtd->erasesize;
-                               memset(&erase_info,
-                                       0, sizeof(struct erase_info));
-                               erase_info.mtd = mtd;
-                               erase_info.addr = addr;
-                               erase_info.len = mtd->erasesize;
                                _aml_rsv_disprotect();
-                               error = mtd->_erase(mtd, &erase_info);
+                               page = (int)(addr >> chip->page_shift);
+                               chipnr = (int)(addr >> chip->chip_shift);
+                               chip->select_chip(mtd, chipnr);
+                               error = chip->erase(mtd, page & chip->pagemask);
+                               chip->select_chip(mtd, -1);
                                _aml_rsv_protect();
                                nandrsv_info->valid_node->ec++;
                                pr_info("---erase bad env block:%llx\n", addr);
@@ -691,7 +690,10 @@ RE_SEARCH:
        pr_info("%s:%d,save info to %llx\n", __func__, __LINE__, addr);
 
        if (nandrsv_info->valid_node->phy_page_addr == 0) {
-               error = mtd->_block_isbad(mtd, addr);
+               chipnr = (int)(addr >> chip->chip_shift);
+               chip->select_chip(mtd, chipnr);
+               error = chip->block_bad(mtd, addr);
+               chip->select_chip(mtd, -1);
                if (error != 0) {
                        /*
                         *bad block here, need fix it
@@ -706,16 +708,18 @@ RE_SEARCH:
                        goto RE_SEARCH;
                }
 
-               memset(&erase_info, 0, sizeof(struct erase_info));
-               erase_info.mtd = mtd;
-               erase_info.addr = addr;
-               erase_info.len = mtd->erasesize;
                _aml_rsv_disprotect();
-               error = mtd->_erase(mtd, &erase_info);
+               page = (int)(addr >> chip->page_shift);
+               //chipnr = (int)(addr >> chip->chip_shift);
+               chip->select_chip(mtd, chipnr);
+               error = chip->erase(mtd, page & chip->pagemask);
+               chip->select_chip(mtd, -1);
                _aml_rsv_protect();
                if (error) {
                        pr_info("env free blk erase failed %d\n", error);
-                       mtd->_block_markbad(mtd, addr);
+                       chip->select_chip(mtd, chipnr);
+                       chip->block_markbad(mtd, addr);
+                       chip->select_chip(mtd, -1);
                        return error;
                }
                nandrsv_info->valid_node->ec++;
@@ -941,20 +945,21 @@ int aml_nand_free_rsv_info(struct mtd_info *mtd,
        struct free_node_t *tmp_node, *next_node = NULL;
        int error = 0;
        loff_t addr = 0;
-       struct erase_info erase_info;
+       int page, chipnr;
+       struct nand_chip *chip = mtd_to_nand(mtd);
 
        pr_info("free %s:\n", nandrsv_info->name);
 
        if (nandrsv_info->valid) {
                addr = nandrsv_info->valid_node->phy_blk_addr;
                addr *= mtd->erasesize;
-               memset(&erase_info,
-                       0, sizeof(struct erase_info));
-               erase_info.mtd = mtd;
-               erase_info.addr = addr;
-               erase_info.len = mtd->erasesize;
+
+               page = (int)(addr >> chip->page_shift);
+               chipnr = (int)(addr >> chip->chip_shift);
                _aml_rsv_disprotect();
-               error = mtd->_erase(mtd, &erase_info);
+               chip->select_chip(mtd, chipnr);
+               error = chip->erase(mtd, page & chip->pagemask);
+               chip->select_chip(mtd, -1);
                _aml_rsv_protect();
                pr_info("erasing valid info block: %llx\n", addr);
                nandrsv_info->valid_node->phy_blk_addr = -1;
@@ -980,7 +985,6 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd,
 {
        struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
        struct nand_chip *chip = &aml_chip->chip;
-       struct mtd_oob_ops aml_oob_ops;
        struct oobinfo_t *oobinfo;
        struct free_node_t *free_node, *tmp_node = NULL;
        unsigned char oob_buf[sizeof(struct oobinfo_t)];
@@ -990,6 +994,7 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd,
        int phys_erase_shift, pages_per_blk, page_num;
        int error = 0, ret = 0;
        uint32_t  remainder;
+       int page, realpage, chipnr;
 
        data_buf = aml_chip->rsv_data_buf;
        oobinfo = (struct oobinfo_t *)oob_buf;
@@ -1007,19 +1012,20 @@ RE_RSV_INFO_EXT:
                offset *= start_blk;
                scan_status = 0;
 RE_RSV_INFO:
-       aml_oob_ops.mode = MTD_OPS_AUTO_OOB;
-       aml_oob_ops.len = mtd->writesize;
-       aml_oob_ops.ooblen = sizeof(struct oobinfo_t);
-       aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/
-       aml_oob_ops.datbuf = data_buf;
-       aml_oob_ops.oobbuf = oob_buf;
-
-       memset((unsigned char *)aml_oob_ops.datbuf,
+       memset((unsigned char *)data_buf,
                0x0, mtd->writesize);
-       memset((unsigned char *)aml_oob_ops.oobbuf,
-               0x0, aml_oob_ops.ooblen);
-
-       error = mtd->_read_oob(mtd, offset, &aml_oob_ops);
+       memset((unsigned char *)oob_buf,
+               0x0, sizeof(struct oobinfo_t));
+
+       realpage = (int)(offset >> chip->page_shift);
+       page = realpage & chip->pagemask;
+       chipnr = (int)(offset >> chip->chip_shift);
+
+       chip->select_chip(mtd, chipnr);
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+       error = chip->ecc.read_page(mtd, chip, data_buf,
+                                                         1, page);
+       chip->select_chip(mtd, -1);
        if ((error != 0) && (error != -EUCLEAN)) {
                pr_info("blk check good but read failed: %llx, %d\n",
                        (uint64_t)offset, error);
@@ -1033,6 +1039,7 @@ RE_RSV_INFO:
                goto RE_RSV_INFO;
        }
 
+       memcpy(oob_buf, chip->oob_poi, mtd->oobavail);
        nandrsv_info->init = 1;
        nandrsv_info->valid_node->status = 0;
        if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) {
@@ -1121,23 +1128,25 @@ RE_RSV_INFO:
 
        if (nandrsv_info->valid == 1) {
                pr_info("%s %d\n", __func__, __LINE__);
-               aml_oob_ops.mode = MTD_OPS_AUTO_OOB;
-               aml_oob_ops.len = mtd->writesize;
-               aml_oob_ops.ooblen = sizeof(struct oobinfo_t);
-               aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/
-               aml_oob_ops.datbuf = data_buf;
-               aml_oob_ops.oobbuf = oob_buf;
 
        for (i = 0; i < pages_per_blk; i++) {
-               memset((unsigned char *)aml_oob_ops.datbuf,
+               memset((unsigned char *)data_buf,
                        0x0, mtd->writesize);
-               memset((unsigned char *)aml_oob_ops.oobbuf,
-                       0x0, aml_oob_ops.ooblen);
+               memset((unsigned char *)oob_buf,
+                       0x0, sizeof(struct oobinfo_t));
 
                offset = nandrsv_info->valid_node->phy_blk_addr;
                offset *= mtd->erasesize;
                offset += i * mtd->writesize;
-               error = mtd->_read_oob(mtd, offset, &aml_oob_ops);
+
+               realpage = (int)(offset >> chip->page_shift);
+               page = realpage & chip->pagemask;
+               chipnr = (int)(offset >> chip->chip_shift);
+               chip->select_chip(mtd, chipnr);
+               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+               error = chip->ecc.read_page(mtd, chip, data_buf,
+                                                         1, page);
+               chip->select_chip(mtd, -1);
                if ((error != 0) && (error != -EUCLEAN)) {
                        pr_info("blk good but read failed:%llx,%d\n",
                                (uint64_t)offset, error);
@@ -1146,6 +1155,7 @@ RE_RSV_INFO:
                        continue;
                }
 
+               memcpy(oob_buf, chip->oob_poi, mtd->oobavail);
                if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) {
                        good_addr[i] = 1;
                        nandrsv_info->valid_node->phy_page_addr = i;