From: Juergen Borleis <jbe@pengutronix.de>
To: linux-mtd@lists.infradead.org
Cc: Richard Weinberger <richard@nod.at>,
jlauruhn@micron.com, tlinder@codeaurora.org
Subject: Re: [RFC/PATCH 0/5 v2] mtd:ubi: Read disturb and Data retention handling
Date: Mon, 10 Nov 2014 14:12:58 +0100 [thread overview]
Message-ID: <201411101412.58159.jbe@pengutronix.de> (raw)
In-Reply-To: <5460B10E.9060501@nod.at>
[-- Attachment #1: Type: text/plain, Size: 698 bytes --]
Hi Richard,
On Monday 10 November 2014 13:35:26 Richard Weinberger wrote:
[...]
> Can you share your test program? I'd like to run it also on one of my
> boards.
Please find the patch attached. Its intended for the Barebox bootloader and can
be applied to its current git. The "-c" option seems currently somehow broken.
I have to talk to Sascha first.
jbe
--
Pengutronix e.K. | Juergen Borleis |
Industrial Linux Solutions | Phone: +49-5121-206917-5128 |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de/ |
[-- Attachment #2: nand_test_command.patch --]
[-- Type: text/x-diff, Size: 8761 bytes --]
commit f3deffa6abf6ab563eaa1842fa3836351d867f30
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date: Thu Jul 24 10:32:52 2014 +0200
Commands: Add a nand-read-test command
NAND flashes suffer from read disturbance. This means that if a page
is read often enough there will be bitflips. This test tool continuously
reads a bunch of pages and shows a statistic over the number of bitfips
occured after which read iteration. This can be used to test a NAND flash
but also to test a NAND driver. The page reads are optionally compared
to the initial read of the page. If there is a difference, but the driver
has not reported an error the driver is buggy.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
diff --git a/commands/Kconfig b/commands/Kconfig
index d73a393885e9..e1d4fba6bc08 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1800,6 +1800,11 @@ config CMD_NANDTEST
-o OFFS start offset on flash
-l LEN length of flash to test
+config CMD_NAND_READ_TEST
+ tristate
+ depends on NAND
+ prompt "nand read test"
+
config CMD_POWEROFF
tristate
depends on HAS_POWEROFF
diff --git a/commands/Makefile b/commands/Makefile
index b1cdf331c441..66d63c8c869a 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_CMD_SAVEENV) += saveenv.o
obj-$(CONFIG_CMD_LOADENV) += loadenv.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NANDTEST) += nandtest.o
+obj-$(CONFIG_CMD_NAND_READ_TEST) += nand-read-test.o
obj-$(CONFIG_CMD_MEMTEST) += memtest.o
obj-$(CONFIG_CMD_TRUE) += true.o
obj-$(CONFIG_CMD_FALSE) += false.o
diff --git a/commands/nand-read-test.c b/commands/nand-read-test.c
new file mode 100644
index 000000000000..cac219178047
--- /dev/null
+++ b/commands/nand-read-test.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <linux/stat.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <xfuncs.h>
+#include <init.h>
+#include <ioctl.h>
+#include <nand.h>
+#include <linux/mtd/mtd-abi.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <string.h>
+#include <clock.h>
+#include <linux/log2.h>
+#include <linux/mtd/mtd.h>
+
+#define MAXFLIPS 8
+
+/*
+ * NAND flashes suffer from read disturbance. This means that if a page
+ * is read often enough there will be bitflips. This test tool continuously
+ * reads a bunch of pages and shows a statistic over the number of bitfips
+ * occured after which read iteration. This can be used to test a NAND flash
+ * but also to test a NAND driver. The page reads are optionally compared
+ * to the initial read of the page. If there is a difference, but the driver
+ * has not reported an error the driver is buggy.
+ */
+struct status {
+ int flips[MAXFLIPS];
+ int err_it;
+ int err;
+ void *buf;
+ void *failbuf;
+};
+
+static void print_status_one(struct status *s, int page)
+{
+ int i;
+
+ printf("%-3d: ", page);
+
+ for (i = 0; i < MAXFLIPS; i++) {
+ if (s->flips[i] == -1)
+ printf("- ");
+ else
+ printf("%-7d ", s->flips[i]);
+ }
+
+ printf("err: %d @ %d\n", s->err, s->err_it);
+}
+
+int print_status(struct status *status, int num_pages, struct mtd_info *mtd, int iteration)
+{
+ int i, ret;
+
+ printf("\nstatistic after iteration %d:\n\n", iteration);
+
+ printf(" Page no\n");
+ printf(" / 1st bitflip after iteration #\n");
+ printf("| / 2nd bitflip after iteration #\n");
+ printf("| | / 3rd 4th 5th 6th 7th 8th bitflip after iteration #\n");
+ printf("| | | / / / / / / error <errcode> @ iteration #\n");
+ printf("| | | | | | | | | /\n");
+ printf("| | | | | | | | | |\n");
+
+ for (i = 0; i < num_pages; i++) {
+ if (ctrlc())
+ return -EINTR;
+ print_status_one(&status[i], i);
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ struct status *s = &status[i];
+
+ if (ctrlc())
+ return -EINTR;
+
+ if (s->failbuf) {
+ printf("Undetected read failure on page %d:\n", i);
+ printf("Should be:\n");
+ ret = memory_display(s->buf, i * mtd->writesize, mtd->writesize, 4, 0);
+ if (ret)
+ return ret;
+ printf("read instead:\n");
+ ret = memory_display(s->failbuf, i * mtd->writesize, mtd->writesize, 4, 0);
+ if (ret)
+ return ret;
+ }
+ }
+
+ mdelay(200);
+ if (ctrlc())
+ return -EINTR;
+
+ return 0;
+}
+
+static void nand_read_test(struct mtd_info *mtd, int num_pages, int compare)
+{
+ void *_buf;
+ uint64_t start;
+ int i = 0, j, n;
+ loff_t addr;
+ int ret;
+ struct status *status;
+ size_t read;
+ void *pagebuf;
+
+ status = xzalloc(sizeof(struct status) * num_pages);
+ pagebuf = xzalloc(mtd->writesize);
+
+ if (compare) {
+ for (n = 0; n < num_pages; n++) {
+ struct status *s = &status[n];
+
+ addr = n * mtd->writesize;
+ s->buf = malloc(mtd->writesize);
+ if (!s->buf)
+ goto out;
+
+ ret = mtd->read(mtd, addr, mtd->writesize, &read, s->buf);
+ if (ret < 0) {
+ printf("Error while reading compare buffer: %s\n",
+ strerror(-ret));
+ goto out;
+ }
+ }
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ struct status *s = &status[i];
+ for (j = 0; j < MAXFLIPS; j++)
+ s->flips[j] = -1;
+ }
+
+ start = get_time_ns();
+
+ i = 0;
+ while (1) {
+ for (n = 0; n < num_pages; n++) {
+ struct status *s = &status[n];
+ addr = n * mtd->writesize;
+
+ ret = mtd->read(mtd, addr, mtd->writesize, &read, pagebuf);
+ if (ret < 0) {
+ if (!s->err) {
+ s->err_it = i;
+ s->err = ret;
+ }
+ }
+
+ if (ret > 0 && ret <= MAXFLIPS) {
+ if (s->flips[ret - 1] == -1)
+ s->flips[ret - 1] = i;
+ }
+
+ if (compare && ret >= 0 && !s->failbuf && memcmp(s->buf, pagebuf, mtd->writesize))
+ s->failbuf = memdup(pagebuf, mtd->writesize);
+
+ _buf += mtd->writesize;
+ }
+
+ if (ctrlc()) {
+ ret = print_status(status, num_pages, mtd, i);
+ if (ret)
+ goto out;
+ }
+
+ if (is_timeout(start, SECOND * 60)) {
+ printf("iteration: %d\n", i);
+ start = get_time_ns();
+ }
+
+ i++;
+ }
+out:
+ free(pagebuf);
+ for (n = 0; n < num_pages; n++) {
+ struct status *s = &status[n];
+ free(s->buf);
+ free(s->failbuf);
+ }
+
+ free(status);
+
+ return;
+}
+
+static int do_nand_read_test(int argc, char *argv[])
+{
+ int opt, ret, fd;
+ static struct mtd_info_user meminfo;
+ int verbose;
+ int num_pages = 64;
+ int compare = 0;
+
+ while ((opt = getopt(argc, argv, "vn:c")) > 0) {
+ switch (opt) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'n':
+ num_pages = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'c':
+ compare = 1;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind >= argc)
+ return COMMAND_ERROR_USAGE;
+
+ fd = open(argv[optind], O_RDWR);
+ if (fd < 0)
+ return fd;
+
+ ret = ioctl(fd, MEMGETINFO, &meminfo);
+
+ close(fd);
+
+ if (ret)
+ return ret;
+
+ if (num_pages * meminfo.writesize > meminfo.size) {
+ num_pages = meminfo.size >> ilog2(meminfo.writesize);
+ printf("WARNING: Device too small. Limiting to %d pages\n", num_pages);
+ }
+
+ printf("Starting NAND read disturbance test on %s with %d pages\n",
+ argv[optind], num_pages);
+ printf("Hit <ctrl-c> once to show current statistics, twice to stop the test\n");
+
+ nand_read_test(meminfo.mtd, num_pages, compare);
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(nand_read_test)
+BAREBOX_CMD_HELP_TEXT("This test tool continuously reads a bunch of NAND pages and")
+BAREBOX_CMD_HELP_TEXT("Prints a statistic about the number of bitflips and crc errors")
+BAREBOX_CMD_HELP_TEXT("occuring on each page")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-n <npages>", "Specify number of pages to test (64)")
+BAREBOX_CMD_HELP_OPT ("-c", "Compare each page read with the first read")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(nand_read_test)
+ .cmd = do_nand_read_test,
+ BAREBOX_CMD_DESC("NAND read disturbance test")
+ BAREBOX_CMD_OPTS("NANDDEV")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_nand_read_test_help)
+BAREBOX_CMD_END
next prev parent reply other threads:[~2014-11-10 13:12 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <201411101307.03225.jbe@pengutronix.de>
2014-11-10 12:35 ` [RFC/PATCH 0/5 v2] mtd:ubi: Read disturb and Data retention handling Richard Weinberger
2014-11-10 13:12 ` Juergen Borleis [this message]
2014-11-11 9:23 ` Richard Weinberger
2014-11-10 13:13 ` Ricard Wanderlof
2014-11-10 13:42 ` Juergen Borleis
2014-11-10 13:52 ` Ricard Wanderlof
2014-10-26 13:49 Tanya Brokhman
2014-10-26 13:49 ` Tanya Brokhman
2014-10-26 20:39 ` Richard Weinberger
2014-10-26 20:39 ` Richard Weinberger
2014-10-27 8:41 ` Tanya Brokhman
2014-10-27 8:41 ` Tanya Brokhman
2014-10-27 8:56 ` Richard Weinberger
2014-10-27 8:56 ` Richard Weinberger
2014-10-29 11:03 ` Tanya Brokhman
2014-10-29 12:00 ` Richard Weinberger
2014-10-31 13:12 ` Tanya Brokhman
2014-10-31 15:34 ` Richard Weinberger
2014-10-31 15:39 ` Richard Weinberger
2014-10-31 22:55 ` Jeff Lauruhn (jlauruhn)
2014-11-02 13:30 ` Tanya Brokhman
2014-11-07 9:21 ` Artem Bityutskiy
2014-11-07 9:21 ` Artem Bityutskiy
2014-11-02 13:25 ` Tanya Brokhman
2014-11-06 8:07 ` Artem Bityutskiy
2014-11-06 8:07 ` Artem Bityutskiy
2014-11-06 12:16 ` Tanya Brokhman
2014-11-07 8:55 ` Artem Bityutskiy
2014-11-07 8:58 ` Artem Bityutskiy
2014-11-11 20:36 ` Tanya Brokhman
2014-11-11 20:36 ` Tanya Brokhman
2014-11-11 21:39 ` Richard Weinberger
2014-11-11 21:39 ` Richard Weinberger
2014-11-12 12:07 ` Artem Bityutskiy
2014-11-12 12:07 ` Artem Bityutskiy
2014-11-12 13:01 ` Richard Weinberger
2014-11-12 13:01 ` Richard Weinberger
2014-11-12 13:32 ` Artem Bityutskiy
2014-11-12 13:32 ` Artem Bityutskiy
2014-11-12 15:37 ` Richard Weinberger
2014-11-12 15:37 ` Richard Weinberger
2014-11-12 11:55 ` Artem Bityutskiy
2014-11-12 11:55 ` Artem Bityutskiy
2014-11-13 12:13 ` Tanya Brokhman
2014-11-13 12:13 ` Tanya Brokhman
2014-11-13 13:36 ` Artem Bityutskiy
2014-11-13 13:36 ` Artem Bityutskiy
2014-11-23 8:13 ` Tanya Brokhman
2014-11-23 8:13 ` Tanya Brokhman
2014-11-02 13:23 ` Tanya Brokhman
2014-11-02 13:54 ` Richard Weinberger
2014-11-02 14:12 ` Tanya Brokhman
2014-11-02 17:02 ` Richard Weinberger
2014-11-02 17:18 ` Tanya Brokhman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201411101412.58159.jbe@pengutronix.de \
--to=jbe@pengutronix.de \
--cc=jlauruhn@micron.com \
--cc=linux-mtd@lists.infradead.org \
--cc=richard@nod.at \
--cc=tlinder@codeaurora.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.