Hello White Ding
Ok, I have put together a patch showing the changes for the yaffs
core. This is attached. I hope it works.
If you can make the patches for the mtd to issue
YAFFS_ECC_RESULT_REFRESH when required then you can send that to me
and we can hook it all up.
Regards Charles
On Thu, Aug 7, 2014 at 12:46 PM, bpqw <
bpqw@micron.com> wrote:
> Hi Charles,
> I am clear,
> Currently there is no YAFFS_ECC_RESULT_REFRESH, so we need to add this case and the threshold as you recommend should be (refresh_threshold + ecc_strength + 1) /2,
> I will plan to create a patch for this.
> Do you have any proposal?
>
> Br
> White Ding
> ____________________________
> EBU APAC Application Engineering
> Tel:86-21-38997078
> Mobile: 86-13761729112
> Address: No 601 Fasai Rd, Waigaoqiao Free Trade Zone Pudong, Shanghai, China
>
> -----Original Message-----
> From: Charles Manning [mailto:cdhmanning@gmail.com]
> Sent: Thursday, August 07, 2014 5:44 AM
> To: bpqw
> Cc: yaffs@lists.aleph1.co.uk
> Subject: Re: [Yaffs] bad block management
>
> On Wed, Aug 6, 2014 at 7:26 PM, bpqw <bpqw@micron.com> wrote:
>> Hi Clarles,
>> We recommended if the bitflip over threshold we just need to refresh the block but not retire it.
>> So we doubt is it reasonable just according to the bitflips over
>> mtd->bitflip_threshold over three times to judge the block as bad block?
>>
>
> Hello White Ding
>
> I certainly understand where you are coming from here.
>
> The concern this raises is that we then lose the safety net of retiring blocks before they go bad.
>
> What we really need is two thresholds in mtd: refresh only, refresh and apply retiring logic.
>
> I suppose we could use bitflip_threshold and bitflip_strength for those, or maybe something slightly different to give more margin.
> Unfortunately the threshold and strength are often set to be the same.
>
> So I would like to use something that can be made up called, say, retire_limit.
> Where
> retire_limit = (refresh_threshold + ecc_strength + 1) /2.
>
>
> For that to work Yaffs needs another level of ECC error.
>
> How about this:
> 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
> };
>
> Then we can have something like, say:
>
> if errors < bitflip_threshold --> NO_ERROR else if errors < retire_limit --> REFRESH else if not corrupted --> FIXED else --> UNFIXED
>
> So for a concrete example, let us say we have something where:
> ecc_strength = 8, bitflip_threshold = 4 then we would have retire_limit = 6
>
> So we would get the following behaviour:
>
> * 0 to 3 errors --> NO_ERROR
> * 4 to 5 errors --> REFRESH (refresh only)
> * 6 to 8 errors -->FIXED (refresh and increment chunk_error_strikes)
> * more than that --> UNFIXED.
>
> Does that make sense?
>
> Charles
From dba051c0183a6ce9f1af61f9ec2b0f09419e48da Mon Sep 17 00:00:00 2001
From: Charles Manning <
cdhmanning@gmail.com>
Date: Thu, 7 Aug 2014 13:21:35 +1200
Subject: [PATCH] Add block refresh handling in yaffs core
THis still needs the drivers to cooperate.
Signed-off-by: Charles Manning <
cdhmanning@gmail.com>
---
yaffs_guts.c | 17 ++++++++++++-----
yaffs_guts.h | 4 +++-
yaffs_nand.c | 2 +-
3 files changed, 16 insertions(+), 7 deletions(-)
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;
}
--
1.9.1