Add block refresh handling in yaffs core
authorCharles Manning <cdhmanning@gmail.com>
Thu, 7 Aug 2014 01:21:35 +0000 (13:21 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Thu, 7 Aug 2014 01:21:35 +0000 (13:21 +1200)
THis still needs the drivers to cooperate.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
yaffs_guts.c
yaffs_guts.h
yaffs_nand.c

index 1c0ae71320a52fc5645e09fd76e5203c348ab8c7..35440d28aed074bcbc26e7ae61e18dd16cd4be7c 100644 (file)
@@ -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,
index 231f8ac567eb86e3583f4c1fc436e9c89a4ca2c8..397aae8cc9c838abcbceca3d9008d94212338643 100644 (file)
@@ -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);
index 0d8499bdc63007490533528b74174e84cd28ea96..a8dae40bd37804c4d396e189b229969723868c92 100644 (file)
@@ -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;
 }