From 9b86955e7e28eaa97159d49dceab3b100cf933a7 Mon Sep 17 00:00:00 2001 From: Jan Remmet Date: Wed, 13 Feb 2019 15:17:46 +0100 Subject: commands: nandtest: provide readonly test Test will read the device and report the corrected or failed ECC states. Signed-off-by: Jan Remmet Signed-off-by: Sascha Hauer --- commands/nandtest.c | 125 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 42 deletions(-) (limited to 'commands') diff --git a/commands/nandtest.c b/commands/nandtest.c index 6d0b770f16..112bb012a5 100644 --- a/commands/nandtest.c +++ b/commands/nandtest.c @@ -67,6 +67,72 @@ static ssize_t __pwrite(int fd, const void *buf, return ret; } +static int _read_get_stats(loff_t ofs, unsigned char *buf, loff_t totallength) +{ + int ret; + + /* Read data from offset */ + pread(fd, buf, meminfo.writesize, ofs); + + ret = ioctl(fd, ECCGETSTATS, &newstats); + if (ret < 0) { + perror("\nECCGETSTATS"); + return ret; + } + + if (newstats.corrected > oldstats.corrected) { + printf("\n %d bit(s) ECC corrected at page 0x%08llx\n", + newstats.corrected - oldstats.corrected, + ofs + memregion.offset); + init_progression_bar(totallength); + show_progress(ofs); + if ((newstats.corrected-oldstats.corrected) >= + MAX_ECC_BITS) { + /* Increment ECC stats that + * are over MAX_ECC_BITS */ + ecc_stats_over++; + } else { + /* Increment ECC stat value */ + ecc_stats[(newstats.corrected - + oldstats.corrected) - 1]++; + } + /* Set oldstats to newstats */ + oldstats.corrected = newstats.corrected; + } + + if (newstats.failed > oldstats.failed) { + printf("\nECC failed at page 0x%08llx\n", + ofs + memregion.offset); + init_progression_bar(totallength); + show_progress(ofs); + oldstats.failed = newstats.failed; + ecc_failed_cnt++; + } + + return 0; +} + +/* + * Read and report correctec ECC bits. + * Param ofs: offset on flash_device. + * Param rbuf: pointer to allocated buffer to copy readed data. + * Param length: length of testing area + */ +static int read_corrected(loff_t ofs, unsigned char *rbuf, loff_t length) +{ + unsigned int i; + int ret; + + for (i = 0; i < meminfo.erasesize; + i += meminfo.writesize) { + ret = _read_get_stats(ofs + i, rbuf + i, length); + if (ret) + return ret; + } + + return 0; +} + /* * Erase and write function. * Param ofs: offset on flash_device. @@ -98,42 +164,9 @@ static int erase_and_write(loff_t ofs, unsigned char *data, __pwrite(fd, data + i, meminfo.writesize, ofs + i, length); - /* Read data from offset */ - pread(fd, rbuf + i, meminfo.writesize, ofs + i); - - ret = ioctl(fd, ECCGETSTATS, &newstats); - if (ret < 0) { - perror("\nECCGETSTATS"); + ret = _read_get_stats(ofs + i, rbuf + i, length); + if (ret) return ret; - } - - if (newstats.corrected > oldstats.corrected) { - printf("\n %d bit(s) ECC corrected at page 0x%08llx\n", - newstats.corrected - oldstats.corrected, - ofs + memregion.offset + i); - init_progression_bar(length); - show_progress(ofs + i); - if ((newstats.corrected-oldstats.corrected) >= - MAX_ECC_BITS) { - /* Increment ECC stats that - * are over MAX_ECC_BITS */ - ecc_stats_over++; - } else { - /* Increment ECC stat value */ - ecc_stats[(newstats.corrected - - oldstats.corrected) - 1]++; - } - /* Set oldstats to newstats */ - oldstats.corrected = newstats.corrected; - } - if (newstats.failed > oldstats.failed) { - printf("\nECC failed at page 0x%08llx\n", - ofs + memregion.offset + i); - init_progression_bar(length); - show_progress(ofs + i); - oldstats.failed = newstats.failed; - ecc_failed_cnt++; - } } /* Compared written data with read data. @@ -171,7 +204,7 @@ static void print_stats(int nr_passes, int length) /* Main program. */ static int do_nandtest(int argc, char *argv[]) { - int opt, do_nandtest_dev = -1, ret = -1; + int opt, do_nandtest_dev = -1, do_nandtest_ro = 0, ret = -1; loff_t flash_offset = 0, test_ofs, length = 0; unsigned int nr_iterations = 1, iter; unsigned char *wbuf, *rbuf; @@ -183,7 +216,7 @@ static int do_nandtest(int argc, char *argv[]) memset(ecc_stats, 0, sizeof(*ecc_stats)); - while ((opt = getopt(argc, argv, "ms:i:o:l:t")) > 0) { + while ((opt = getopt(argc, argv, "ms:i:o:l:tr")) > 0) { switch (opt) { case 'm': markbad = 1; @@ -203,6 +236,10 @@ static int do_nandtest(int argc, char *argv[]) case 't': do_nandtest_dev = 1; break; + case 'r': + do_nandtest_dev = 1; + do_nandtest_ro = 1; + break; default: return COMMAND_ERROR_USAGE; } @@ -213,7 +250,7 @@ static int do_nandtest(int argc, char *argv[]) return COMMAND_ERROR_USAGE; if (do_nandtest_dev == -1) { - printf("Please add -t parameter to start nandtest.\n"); + printf("Please add -t or -r parameter to start nandtest.\n"); return 0; } @@ -306,10 +343,13 @@ static int do_nandtest(int argc, char *argv[]) show_progress(test_ofs); continue; } - - get_random_bytes(wbuf, meminfo.erasesize); - ret = erase_and_write(test_ofs, wbuf, - rbuf, length); + if (do_nandtest_ro) { + ret = read_corrected(test_ofs, rbuf, length); + } else { + get_random_bytes(wbuf, meminfo.erasesize); + ret = erase_and_write(test_ofs, wbuf, + rbuf, length); + } if (ret < 0) goto err2; } @@ -339,6 +379,7 @@ err: BAREBOX_CMD_HELP_START(nandtest) BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-t", "Really do a nandtest on device") +BAREBOX_CMD_HELP_OPT ("-r", "Readonly nandtest on device") BAREBOX_CMD_HELP_OPT ("-m", "Mark blocks bad if they appear so") BAREBOX_CMD_HELP_OPT ("-s SEED", "supply random seed") BAREBOX_CMD_HELP_OPT ("-i ITERATIONS", "nNumber of iterations") -- cgit v1.2.3