mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
MTD: spin_lock stuck problem about marking bad block for mtd driver [1/1]
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
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;
|
||||
|
||||
error = mtd->_read_oob(mtd, addr, &aml_oob_ops);
|
||||
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);
|
||||
memset((unsigned char *)oob_buf,
|
||||
0x0, sizeof(struct oobinfo_t));
|
||||
|
||||
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 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;
|
||||
|
||||
Reference in New Issue
Block a user