[PATCH v5] mtd: gpmi: Deal with bitflips in erased regions regions

Elie De Brauwer eliedebrauwer at gmail.com
Wed Dec 18 02:50:15 EST 2013


On Wed, Dec 18, 2013 at 6:21 AM, Huang Shijie <shijie8 at gmail.com> wrote:
> On Tue, Dec 17, 2013 at 02:45:42PM +0100, Elie De Brauwer wrote:
>>
>> +     /* Set the tolerance for bitflips when reading erased blocks. */
>> +     erase_threshold = gf_len / 2;
>> +     if (erase_threshold > ecc_strength)
>> +             erase_threshold = ecc_strength;
>> +
> I was about to give you my ACK, but i find you used a wrong ecc strength
> here.  The "ecc_strength" is just half of the real ECC strength used by
> the BCH. Please read this line in the function:
> 268     ecc_strength  = bch_geo->ecc_strength >> 1;
>
> Could you please send a new version patch ?
>
>
>> +     writel(erase_threshold & BM_BCH_MODE_ERASE_THRESHOLD_MASK,
>> +             r->bch_regs + HW_BCH_MODE);
>> +
>>       /* Set *all* chip selects to use layout 0. */
>>       writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
>>
>> @@ -1094,6 +1103,15 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
>>       return reg & mask;
>>  }
>>
>> +/*
>> + * Count the number of 0 bits in a supposed to be
>> + * erased region and correct them. Return the number
>> + * of bitflips or zero when the region was correct.
>> + */
>> +static unsigned int erased_sector_bitflips(unsigned char *data,
>> +                                     unsigned int chunk,
>> +                                     struct bch_geometry *geo)
>> +{
>> +     unsigned int flip_bits = 0;
>> +     int i;
>> +     int base = geo->ecc_chunk_size * chunk;
>> +
>> +     /* Count bitflips */
>> +     for (i = 0; i < geo->ecc_chunk_size; i++)
>> +             flip_bits += hweight8(~data[base + i]);
>> +
>> +     /* Correct bitflips by 0xFF'ing this chunk. */
>> +     if (flip_bits)
>> +             memset(&data[base], 0xFF, geo->ecc_chunk_size);
>> +
>> +     return flip_bits;
>> +}
>
> Since a new version patch is inevitable, i want to give more comment
> about this function.
>
>
> Does the following code run faster then above?
> static unsigned int erased_sector_bitflips(unsigned char *data,
>                                         unsigned int chunk,
>                                         struct bch_geometry *geo)
> {
>         unsigned int flip_bits = 0;
>         int i;
>         int base = geo->ecc_chunk_size * chunk;
>         int tmp;
>
>         for (i = 0; i < geo->ecc_chunk_size; i++) {
>                 tmp = hweight8(~data[base + i]);
>
>                 if (tmp) {
>                         data[base + i] = 0xff;
>                         flip_bits += tmp;
>                 }
>         }
>
>         return flip_bits;
> }
>
> I am not sure this code is faster then your code, i do not have time to
> do a test to compare the two functions.
>
> If you think your function is better, just ignore my code, it is okay to
> me.
>
> I really very appreciate at your work!
>


Personally I would think the version you suggest would be more optimal and if
I wouldn't have stolen my version from the omap2 driver it would probably looked
more like the one you suggested. So I wrote up a little benchmark application
(available at: https://github.com/amo-ej1/Code-snippets/blob/master/C_C%2B%2B/bitflips_bench/bitflips_bench.c
)

But the output actually surprises me a bit. on my laptop your
suggestion is about 30% faster.

edb at lapelidb:~/today$ gcc bitflips_bench.c  && ./a.out
omap  : 37103 usec
speedy: 28141 usec
edb at lapelidb:~/today$ gcc -O2 ./bitflips_bench.c
edb at lapelidb:~/today$ ./a.out
omap  : 9530 usec
speedy: 6563 usec

However when testing it on my i.mx283 target  (used gcc 4.8.1) there
hardly isn't any difference
(first one without optimization, the second one with -O2).

root@(none):~# /tmp/a.out
omap  : 616839 usec
speedy: 634944 usec
root@(none):~# /tmp/a.out
omap  : 188134 usec
speedy: 188049 usec

(On 4k chunks, when testing it on 512 byte chunks the omap one
performs even better).

So I'm more tempted to stay at the original version. I will provide a
new version of the patch however with the ecc_strenght modified.

gr
E.
-- 
Elie De Brauwer



More information about the linux-mtd mailing list