mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
mtd: nand: enhance the robust of env
PD#145594: nand: enhance the robust of env 1)enhance sudden power lost and ecc-error protection 2)add mtd env mutex for kernel Change-Id: I0a454149c408f882924543d84db5d46591230d3d Signed-off-by: Yonghui Yu <yonghui.yu@amlogic.com>
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <linux/device.h>
|
||||
|
||||
#define ENV_NAME "nand_env"
|
||||
static DEFINE_MUTEX(env_mutex);
|
||||
static dev_t uboot_env_no;
|
||||
struct cdev uboot_env;
|
||||
struct device *uboot_dev;
|
||||
@@ -151,12 +152,13 @@ ssize_t env_store(struct class *class, struct class_attribute *attr,
|
||||
int ret = 0;
|
||||
u8 *env_ptr = NULL;
|
||||
|
||||
pr_info("env_store : #####\n");
|
||||
|
||||
env_ptr = kzalloc(CONFIG_ENV_SIZE, GFP_KERNEL);
|
||||
if (env_ptr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&env_mutex);
|
||||
pr_info("env_store : #####\n");
|
||||
ret = amlnf_env_read(env_ptr, CONFIG_ENV_SIZE);
|
||||
if (ret) {
|
||||
pr_info("nand_env_read: nand env read failed\n");
|
||||
@@ -172,6 +174,7 @@ ssize_t env_store(struct class *class, struct class_attribute *attr,
|
||||
}
|
||||
|
||||
pr_info("env_store : OK #####\n");
|
||||
mutex_unlock(&env_mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -202,6 +205,7 @@ 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);
|
||||
|
||||
/*amlnand_get_device(aml_chip_env, CHIP_READING);*/
|
||||
ret = amlnf_env_read((u8 *)env_ptr, CONFIG_ENV_SIZE);
|
||||
@@ -220,6 +224,7 @@ 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);
|
||||
/*amlnand_release_device(aml_chip_env);*/
|
||||
vfree(env_ptr);
|
||||
return read_size;
|
||||
@@ -245,6 +250,7 @@ ssize_t uboot_env_write(struct file *file,
|
||||
if (env_ptr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&env_mutex);
|
||||
/*not need nand_get_device here, mtd->_read_xx will done with it*/
|
||||
/*nand_get_device(mtd, FL_WRITING);*/
|
||||
ret = amlnf_env_read((u8 *)env_ptr, CONFIG_ENV_SIZE);
|
||||
@@ -270,6 +276,7 @@ ssize_t uboot_env_write(struct file *file,
|
||||
|
||||
*ppos += write_size;
|
||||
exit:
|
||||
mutex_unlock(&env_mutex);
|
||||
/*nand_release_device(mtd);*/
|
||||
vfree(env_ptr);
|
||||
return write_size;
|
||||
|
||||
@@ -310,6 +310,9 @@ struct aml_nandrsv_info_t {
|
||||
u_char part_num_before_sys;
|
||||
};
|
||||
|
||||
/*define abnormal state for reserved area*/
|
||||
#define POWER_ABNORMAL_FLAG 0x01
|
||||
#define ECC_ABNORMAL_FLAG 0x02
|
||||
struct valid_node_t {
|
||||
int16_t ec;
|
||||
int16_t phy_blk_addr;
|
||||
|
||||
@@ -82,36 +82,42 @@ static void release_free_node(struct mtd_info *mtd,
|
||||
int aml_nand_rsv_erase_protect(struct mtd_info *mtd, unsigned int block_addr)
|
||||
{
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
unsigned int bbt_start, bbt_end, key_start, key_end;
|
||||
|
||||
if (!_aml_rsv_isprotect())
|
||||
return 0;
|
||||
|
||||
bbt_start = aml_chip->aml_nandbbt_info->start_block;
|
||||
bbt_end = aml_chip->aml_nandbbt_info->end_block;
|
||||
key_start = aml_chip->aml_nandkey_info->start_block;
|
||||
key_end = aml_chip->aml_nandkey_info->end_block;
|
||||
|
||||
#ifdef AML_NAND_UBOOT
|
||||
if (aml_chip->aml_nandkey_info != NULL) {
|
||||
if (aml_chip->aml_nandkey_info->valid)
|
||||
if ((!(info_disprotect & DISPROTECT_KEY))
|
||||
&& ((block_addr >= aml_chip->aml_nandkey_info->start_block)
|
||||
&& (block_addr < aml_chip->aml_nandkey_info->end_block)))
|
||||
return -1; /*need skip key blocks*/
|
||||
&& ((block_addr >= key_start)
|
||||
&& (block_addr < key_end)))
|
||||
return -1; /*need skip key blocks*/
|
||||
}
|
||||
if (aml_chip->aml_nandbbt_info != NULL) {
|
||||
if (aml_chip->aml_nandbbt_info->valid)
|
||||
if ((block_addr >= aml_chip->aml_nandbbt_info->start_block)
|
||||
&& (block_addr < aml_chip->aml_nandbbt_info->end_block))
|
||||
return -1; /*need skip bbt blocks*/
|
||||
if ((block_addr >= bbt_start)
|
||||
&& (block_addr < bbt_end))
|
||||
return -1; /*need skip bbt blocks*/
|
||||
}
|
||||
#else
|
||||
if (aml_chip->aml_nandkey_info != NULL) {
|
||||
if (aml_chip->aml_nandkey_info->valid)
|
||||
if ((block_addr >= aml_chip->aml_nandkey_info->start_block)
|
||||
&& (block_addr < aml_chip->aml_nandkey_info->end_block))
|
||||
return -1; /*need skip key blocks*/
|
||||
if ((block_addr >= key_start)
|
||||
&& (block_addr < key_end))
|
||||
return -1; /*need skip key blocks*/
|
||||
}
|
||||
if (aml_chip->aml_nandbbt_info != NULL) {
|
||||
if (aml_chip->aml_nandbbt_info->valid)
|
||||
if ((block_addr >= aml_chip->aml_nandbbt_info->start_block)
|
||||
&& (block_addr < aml_chip->aml_nandbbt_info->end_block))
|
||||
return -1; /*need skip bbt blocks*/
|
||||
if ((block_addr >= bbt_start)
|
||||
&& (block_addr < bbt_end))
|
||||
return -1; /*need skip bbt blocks*/
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@@ -598,6 +604,11 @@ int aml_nand_save_rsv_info(struct mtd_info *mtd,
|
||||
struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
|
||||
|
||||
pages_per_blk = mtd->erasesize / mtd->writesize;
|
||||
/*solve these abnormals caused by power off and ecc error*/
|
||||
if ((nandrsv_info->valid_node->status & POWER_ABNORMAL_FLAG)
|
||||
|| (nandrsv_info->valid_node->status & ECC_ABNORMAL_FLAG))
|
||||
nandrsv_info->valid_node->phy_page_addr = pages_per_blk;
|
||||
|
||||
if ((mtd->writesize < nandrsv_info->size)
|
||||
&& (aml_chip->aml_nandenv_info->valid == 1))
|
||||
i = (nandrsv_info->size + mtd->writesize - 1) / mtd->writesize;
|
||||
@@ -612,7 +623,6 @@ RE_SEARCH:
|
||||
nandrsv_info->valid_node->phy_page_addr += i;
|
||||
if ((nandrsv_info->valid_node->phy_page_addr+i) > pages_per_blk) {
|
||||
if ((nandrsv_info->valid_node->phy_page_addr - i) == pages_per_blk) {
|
||||
nandrsv_info->valid_node->status = 0;
|
||||
addr = nandrsv_info->valid_node->phy_blk_addr;
|
||||
addr *= mtd->erasesize;
|
||||
memset(&erase_info,
|
||||
@@ -623,7 +633,6 @@ if ((nandrsv_info->valid_node->phy_page_addr+i) > pages_per_blk) {
|
||||
_aml_rsv_disprotect();
|
||||
error = mtd->_erase(mtd, &erase_info);
|
||||
_aml_rsv_protect();
|
||||
nandrsv_info->valid_node->status = 1;
|
||||
nandrsv_info->valid_node->ec++;
|
||||
pr_info("---erase bad env block:%llx\n", addr);
|
||||
}
|
||||
@@ -687,7 +696,6 @@ if ((nandrsv_info->valid_node->phy_page_addr+i) > pages_per_blk) {
|
||||
erase_info.mtd = mtd;
|
||||
erase_info.addr = addr;
|
||||
erase_info.len = mtd->erasesize;
|
||||
nandrsv_info->valid_node->status = 0;
|
||||
_aml_rsv_disprotect();
|
||||
error = mtd->_erase(mtd, &erase_info);
|
||||
_aml_rsv_protect();
|
||||
@@ -697,7 +705,6 @@ if ((nandrsv_info->valid_node->phy_page_addr+i) > pages_per_blk) {
|
||||
return error;
|
||||
}
|
||||
nandrsv_info->valid_node->ec++;
|
||||
nandrsv_info->valid_node->status = 1;
|
||||
}
|
||||
|
||||
if (aml_nand_write_rsv(mtd, nandrsv_info, addr, (u_char *) buf)) {
|
||||
@@ -705,6 +712,8 @@ if ((nandrsv_info->valid_node->phy_page_addr+i) > pages_per_blk) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* clear status when write successfully*/
|
||||
nandrsv_info->valid_node->status = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -815,7 +824,6 @@ int aml_nand_rsv_info_init(struct mtd_info *mtd)
|
||||
return -ENOMEM;
|
||||
|
||||
aml_chip->aml_nandbbt_info->valid_node->phy_blk_addr = -1;
|
||||
aml_chip->aml_nandbbt_info->valid_node->status = 1;
|
||||
aml_chip->aml_nandbbt_info->start_block = bbt_start_block;
|
||||
aml_chip->aml_nandbbt_info->end_block =
|
||||
aml_chip->aml_nandbbt_info->start_block + 4;
|
||||
@@ -844,7 +852,6 @@ int aml_nand_rsv_info_init(struct mtd_info *mtd)
|
||||
return -ENOMEM;
|
||||
|
||||
aml_chip->aml_nandenv_info->valid_node->phy_blk_addr = -1;
|
||||
aml_chip->aml_nandenv_info->valid_node->status = 1;
|
||||
aml_chip->aml_nandenv_info->start_block =
|
||||
aml_chip->aml_nandbbt_info->end_block;
|
||||
aml_chip->aml_nandenv_info->end_block =
|
||||
@@ -865,7 +872,6 @@ int aml_nand_rsv_info_init(struct mtd_info *mtd)
|
||||
return -ENOMEM;
|
||||
|
||||
aml_chip->aml_nandkey_info->valid_node->phy_blk_addr = -1;
|
||||
aml_chip->aml_nandkey_info->valid_node->status = 1;
|
||||
aml_chip->aml_nandkey_info->start_block =
|
||||
aml_chip->aml_nandenv_info->end_block;
|
||||
aml_chip->aml_nandkey_info->end_block =
|
||||
@@ -886,7 +892,6 @@ int aml_nand_rsv_info_init(struct mtd_info *mtd)
|
||||
return -ENOMEM;
|
||||
|
||||
aml_chip->aml_nanddtb_info->valid_node->phy_blk_addr = -1;
|
||||
aml_chip->aml_nanddtb_info->valid_node->status = 1;
|
||||
aml_chip->aml_nanddtb_info->start_block =
|
||||
aml_chip->aml_nandkey_info->end_block;
|
||||
aml_chip->aml_nanddtb_info->end_block =
|
||||
@@ -979,6 +984,7 @@ RE_RSV_INFO:
|
||||
|
||||
/* pr_info("%s %d\n", __func__, __LINE__); */
|
||||
nandrsv_info->init = 1;
|
||||
nandrsv_info->valid_node->status = 0;
|
||||
if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) {
|
||||
/* pr_info("%s %d\n", __func__, __LINE__); */
|
||||
nandrsv_info->valid = 1;
|
||||
|
||||
Reference in New Issue
Block a user