static loff_t offset; /* Offset of the page we're using. */ staticunsigned eraseblock; /* Eraseblock number for our page. */
/* We assume that the ECC can correct up to a certain number
* of biterrors per subpage. */ staticunsigned subsize; /* Size of subpages */ staticunsigned subcount; /* Number of subpages per page */
staticstruct mtd_info *mtd; /* MTD device */
static uint8_t *wbuffer; /* One page write / compare buffer */ static uint8_t *rbuffer; /* One page read buffer */
/* 'random' bytes from known offsets */ static uint8_t hash(unsigned offset)
{ unsigned v = offset; unsignedchar c;
v ^= 0x7f7edfd3;
v = v ^ (v >> 3);
v = v ^ (v >> 5);
v = v ^ (v >> 13);
c = v & 0xFF; /* Reverse bits of result. */
c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
c = (c & 0x55) << 1 | (c & 0xAA) >> 1; return c;
}
/* Writes wbuffer to page */ staticint write_page(int log)
{ if (log)
pr_info("write_page\n");
/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
* or error (<0) */ staticint read_page(int log)
{ int err = 0;
size_t read; struct mtd_ecc_stats oldstats;
if (log)
pr_info("read_page\n");
/* Saving last mtd stats */
memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
/* Finds the first '1' bit in wbuffer starting at offset 'byte'
* and sets it to '0'. */ staticint insert_biterror(unsigned byte)
{ int bit;
while (byte < mtd->writesize) { for (bit = 7; bit >= 0; bit--) { if (CBIT(wbuffer[byte], bit)) {
BCLR(wbuffer[byte], bit);
pr_info("Inserted biterror @ %u/%u\n", byte, bit); return 0;
}
}
byte++;
}
pr_err("biterror: Failed to find a '1' bit\n"); return -EIO;
}
/* Writes 'random' data to page and then introduces deliberate bit
* errors into the page, while verifying each step. */ staticint incremental_errors_test(void)
{ int err = 0; unsigned i; unsigned errs_per_subpage = 0;
pr_info("incremental biterrors test\n");
for (i = 0; i < mtd->writesize; i++)
wbuffer[i] = hash(i+seed);
err = write_page(1); if (err) gotoexit;
while (1) {
err = rewrite_page(1); if (err) gotoexit;
err = read_page(1); if (err > 0)
pr_info("Read reported %d corrected bit errors\n", err); if (err < 0) {
pr_err("After %d biterrors per subpage, read reported error %d\n",
errs_per_subpage, err);
err = 0; gotoexit;
}
err = verify_page(1); if (err) {
pr_err("ECC failure, read data is incorrect despite read success\n"); gotoexit;
}
pr_info("Successfully corrected %d bit errors per subpage\n",
errs_per_subpage);
for (i = 0; i < subcount; i++) {
err = insert_biterror(i * subsize); if (err < 0) gotoexit;
}
errs_per_subpage++;
}
exit: return err;
}
/* Writes 'random' data to page and then re-writes that same data repeatedly. This eventually develops bit errors (bits written as '1' will slowly become
'0'), which are corrected as far as the ECC is capable of. */ staticint overwrite_test(void)
{ int err = 0; unsigned i; unsigned max_corrected = 0; unsigned opno = 0; /* We don't expect more than this many correctable bit errors per
* page. */ #define MAXBITS 512 staticunsigned bitstats[MAXBITS]; /* bit error histogram. */
memset(bitstats, 0, sizeof(bitstats));
pr_info("overwrite biterrors test\n");
for (i = 0; i < mtd->writesize; i++)
wbuffer[i] = hash(i+seed);
err = write_page(1); if (err) gotoexit;
while (opno < max_overwrite) {
err = write_page(0); if (err) break;
err = read_page(0); if (err >= 0) { if (err >= MAXBITS) {
pr_info("Implausible number of bit errors corrected\n");
err = -EIO; break;
}
bitstats[err]++; if (err > max_corrected) {
max_corrected = err;
pr_info("Read reported %d corrected bit errors\n",
err);
}
} else { /* err < 0 */
pr_info("Read reported error %d\n", err);
err = 0; break;
}
err = verify_page(0); if (err) {
bitstats[max_corrected] = opno;
pr_info("ECC failure, read data is incorrect despite read success\n"); break;
}
err = mtdtest_relax(); if (err) break;
opno++;
}
/* At this point bitstats[0] contains the number of ops with no bit
* errors, bitstats[1] the number of ops with 1 bit error, etc. */
pr_info("Bit error histogram (%d operations total):\n", opno); for (i = 0; i < max_corrected; i++)
pr_info("Page reads with %3d corrected bit errors: %d\n",
i, bitstats[i]);
exit: return err;
}
staticint __init mtd_nandbiterrs_init(void)
{ int err = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.