From: Charles Manning Date: Thu, 7 Aug 2014 01:21:35 +0000 (+1200) Subject: Add block refresh handling in yaffs core X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=dba051c0183a6ce9f1af61f9ec2b0f09419e48da Add block refresh handling in yaffs core THis still needs the drivers to cooperate. Signed-off-by: Charles Manning --- diff --git a/yaffs_guts.c b/yaffs_guts.c index 1c0ae71..35440d2 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -211,11 +211,18 @@ static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk, } void yaffs_handle_chunk_error(struct yaffs_dev *dev, - struct yaffs_block_info *bi) + struct yaffs_block_info *bi, + enum yaffs_ecc_result err_type) { - if (!bi->gc_prioritise) { - bi->gc_prioritise = 1; - dev->has_pending_prioritised_gc = 1; + if (bi->gc_prioritise) + return; + + /* We need to refresh this data by gc'ing the block soon. */ + bi->gc_prioritise = 1; + dev->has_pending_prioritised_gc = 1; + + /* If it was more than just refresh request then consider retirement. */ + if (err_type > YAFFS_ECC_RESULT_REFRESH) { bi->chunk_error_strikes++; if (bi->chunk_error_strikes > 3) { @@ -233,7 +240,7 @@ static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk, int flash_block = nand_chunk / dev->param.chunks_per_block; struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block); - yaffs_handle_chunk_error(dev, bi); + yaffs_handle_chunk_error(dev, bi, YAFFS_ECC_RESULT_FIXED); if (erased_ok) { /* Was an actual write failure, diff --git a/yaffs_guts.h b/yaffs_guts.h index 231f8ac..397aae8 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -163,6 +163,7 @@ union yaffs_tags_union { enum yaffs_ecc_result { YAFFS_ECC_RESULT_UNKNOWN, YAFFS_ECC_RESULT_NO_ERROR, + YAFFS_ECC_RESULT_REFRESH, YAFFS_ECC_RESULT_FIXED, YAFFS_ECC_RESULT_UNFIXED }; @@ -940,7 +941,8 @@ void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, int lyn); int yaffs_check_ff(u8 *buffer, int n_bytes); void yaffs_handle_chunk_error(struct yaffs_dev *dev, - struct yaffs_block_info *bi); + struct yaffs_block_info *bi, + enum yaffs_ecc_result err_type); u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev); void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer); diff --git a/yaffs_nand.c b/yaffs_nand.c index 0d8499b..a8dae40 100644 --- a/yaffs_nand.c +++ b/yaffs_nand.c @@ -42,7 +42,7 @@ int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, bi = yaffs_get_block_info(dev, nand_chunk / dev->param.chunks_per_block); - yaffs_handle_chunk_error(dev, bi); + yaffs_handle_chunk_error(dev, bi, tags->ecc_result); } return result; }