[QUESTION] MLC NAND and ECC over OOB area
Charles Hardin
ckhardin at exablox.com
Thu Oct 11 14:22:18 EDT 2012
On Oct 10, 2012, at 11:13 AM, Ivan Djelic wrote:
>
> Hi Charles,
>
> The OOB area is primarily used to store:
> - a bad block marker
> - ECC bytes
>
> The ECC is generally designed to protect the data area, and the ECC bytes themselves (data+ECC bytes form a long codeword).
> The bad block marker normally has two useful values only: 0xff or 0x00, therefore it can be successfully read even with
> several bitflips, by looking at its Hamming weight (the number of 1s in the byte).
>
> Now, if you want to store additional stuff (metadata) in the OOB area, _then_ you will need an ECC that covers data + metadata.
> This is possible with some drivers; this can also be done with the software BCH library (with a patch).
>
> But the general trend is to avoid using the OOB area for that, because you never know how much space the next NAND generation
> will require for ECC, and you'll be in trouble once your metadata does not fit anymore in the remaining space.
>
> BR,
> --
> Ivan
Ok, that seems reasonable - and, following this line of thought - then the expectation would be to change the nand_bbt.c code to check for the "weight of a bad block pattern" instead of looking for an exact match on the pattern.
For example the following would change:
/**
* check_short_pattern - [GENERIC] check if a pattern is in the buffer
* @buf: the buffer to search
* @td: search pattern descriptor
*
* Check for a pattern at the given place. Used to search bad block tables and
* good / bad block identifiers. Same as check_pattern, but no optional empty
* check.
*/
static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
{
int i;
uint8_t *p = buf;
/* Compare the pattern */
for (i = 0; i < td->len; i++) {
if (p[td->offs + i] != td->pattern[i])
return -1;
}
return 0;
}
to something like the pseudo code below:
static in check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
{
int i;
int weight = 0;
int tweight = 0;
uint8_t *p = buf;
/* Compute and compare the weight */
for (i = 0; i < td->len; i++) {
uint8_t w;
w = p[td->offs+i];
w = (w & 0x55) + ((w >> 1) & 0x55);
w = (w & 0x33) + ((w >> 2) & 0x33);
w = (w & 0x0f) + ((w >> 4) & 0x0f);
weight += w;
w = td->pattern[i];
w = (w & 0x55) + ((w >> 1) & 0x55);
w = (w & 0x33) + ((w >> 2) & 0x33);
w = (w & 0x0f) + ((w >> 4) & 0x0f);
tweight += w;
}
/* if the weight of the buf is more then half the weight of the pattern */
if (weight > (tweight / 2))
return 0;
return -1;
}
This is a not an overly complex concept for nand_bbt code path, but it would change the exact match done currently to a heuristic match done by weight. My guess is that this behavior change will be done by the driver itself and override the nand_scan_bbt functions. However, I don't see an interface to plugin a specific BBT implementation in the underneath the nand_scan_bbt and nand_update_bbt functions currently in the hand drivers.
Regards,
Charles
--
Bits go in, bytes go out
More information about the linux-mtd
mailing list