1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright © 2012 NetCommWireless
4 * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
6 * Test for multi-bit error recovery on a NAND page This mostly tests the
7 * ECC controller / driver.
9 * There are two test modes:
11 * 0 - artificially inserting bit errors until the ECC fails
12 * This is the default method and fairly quick. It should
13 * be independent of the quality of the FLASH.
15 * 1 - re-writing the same pattern repeatedly until the ECC fails.
16 * This method relies on the physics of NAND FLASH to eventually
17 * generate '0' bits if '1' has been written sufficient times.
18 * Depending on the NAND, the first bit errors will appear after
19 * 1000 or more writes and then will usually snowball, reaching the
20 * limits of the ECC quickly.
22 * The test stops after 10000 cycles, should your FLASH be
23 * exceptionally good and not generate bit errors before that. Try
24 * a different page in that case.
26 * Please note that neither of these tests will significantly 'use up' any
27 * FLASH endurance. Only a maximum of two erase operations will be performed.
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/init.h>
33 #include <linux/module.h>
34 #include <linux/moduleparam.h>
35 #include <linux/mtd/mtd.h>
36 #include <linux/err.h>
37 #include <linux/mtd/rawnand.h>
38 #include <linux/slab.h>
42 module_param(dev
, int, S_IRUGO
);
43 MODULE_PARM_DESC(dev
, "MTD device number to use");
45 static unsigned page_offset
;
46 module_param(page_offset
, uint
, S_IRUGO
);
47 MODULE_PARM_DESC(page_offset
, "Page number relative to dev start");
50 module_param(seed
, uint
, S_IRUGO
);
51 MODULE_PARM_DESC(seed
, "Random seed");
54 module_param(mode
, int, S_IRUGO
);
55 MODULE_PARM_DESC(mode
, "0=incremental errors, 1=overwrite test");
57 static unsigned max_overwrite
= 10000;
59 static loff_t offset
; /* Offset of the page we're using. */
60 static unsigned eraseblock
; /* Eraseblock number for our page. */
62 /* We assume that the ECC can correct up to a certain number
63 * of biterrors per subpage. */
64 static unsigned subsize
; /* Size of subpages */
65 static unsigned subcount
; /* Number of subpages per page */
67 static struct mtd_info
*mtd
; /* MTD device */
69 static uint8_t *wbuffer
; /* One page write / compare buffer */
70 static uint8_t *rbuffer
; /* One page read buffer */
72 /* 'random' bytes from known offsets */
73 static uint8_t hash(unsigned offset
)
82 /* Reverse bits of result. */
83 c
= (c
& 0x0F) << 4 | (c
& 0xF0) >> 4;
84 c
= (c
& 0x33) << 2 | (c
& 0xCC) >> 2;
85 c
= (c
& 0x55) << 1 | (c
& 0xAA) >> 1;
89 /* Writes wbuffer to page */
90 static int write_page(int log
)
93 pr_info("write_page\n");
95 return mtdtest_write(mtd
, offset
, mtd
->writesize
, wbuffer
);
98 /* Re-writes the data area while leaving the OOB alone. */
99 static int rewrite_page(int log
)
102 struct mtd_oob_ops ops
;
105 pr_info("rewrite page\n");
107 ops
.mode
= MTD_OPS_RAW
; /* No ECC */
108 ops
.len
= mtd
->writesize
;
113 ops
.datbuf
= wbuffer
;
116 err
= mtd_write_oob(mtd
, offset
, &ops
);
117 if (err
|| ops
.retlen
!= mtd
->writesize
) {
118 pr_err("error: write_oob failed (%d)\n", err
);
126 /* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
128 static int read_page(int log
)
132 struct mtd_ecc_stats oldstats
;
135 pr_info("read_page\n");
137 /* Saving last mtd stats */
138 memcpy(&oldstats
, &mtd
->ecc_stats
, sizeof(oldstats
));
140 err
= mtd_read(mtd
, offset
, mtd
->writesize
, &read
, rbuffer
);
141 if (!err
|| err
== -EUCLEAN
)
142 err
= mtd
->ecc_stats
.corrected
- oldstats
.corrected
;
144 if (err
< 0 || read
!= mtd
->writesize
) {
145 pr_err("error: read failed at %#llx\n", (long long)offset
);
153 /* Verifies rbuffer against random sequence */
154 static int verify_page(int log
)
156 unsigned i
, errs
= 0;
159 pr_info("verify_page\n");
161 for (i
= 0; i
< mtd
->writesize
; i
++) {
162 if (rbuffer
[i
] != hash(i
+seed
)) {
163 pr_err("Error: page offset %u, expected %02x, got %02x\n",
164 i
, hash(i
+seed
), rbuffer
[i
]);
175 #define CBIT(v, n) ((v) & (1 << (n)))
176 #define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
178 /* Finds the first '1' bit in wbuffer starting at offset 'byte'
179 * and sets it to '0'. */
180 static int insert_biterror(unsigned byte
)
184 while (byte
< mtd
->writesize
) {
185 for (bit
= 7; bit
>= 0; bit
--) {
186 if (CBIT(wbuffer
[byte
], bit
)) {
187 BCLR(wbuffer
[byte
], bit
);
188 pr_info("Inserted biterror @ %u/%u\n", byte
, bit
);
194 pr_err("biterror: Failed to find a '1' bit\n");
198 /* Writes 'random' data to page and then introduces deliberate bit
199 * errors into the page, while verifying each step. */
200 static int incremental_errors_test(void)
204 unsigned errs_per_subpage
= 0;
206 pr_info("incremental biterrors test\n");
208 for (i
= 0; i
< mtd
->writesize
; i
++)
209 wbuffer
[i
] = hash(i
+seed
);
217 err
= rewrite_page(1);
223 pr_info("Read reported %d corrected bit errors\n", err
);
225 pr_err("After %d biterrors per subpage, read reported error %d\n",
226 errs_per_subpage
, err
);
231 err
= verify_page(1);
233 pr_err("ECC failure, read data is incorrect despite read success\n");
237 pr_info("Successfully corrected %d bit errors per subpage\n",
240 for (i
= 0; i
< subcount
; i
++) {
241 err
= insert_biterror(i
* subsize
);
253 /* Writes 'random' data to page and then re-writes that same data repeatedly.
254 This eventually develops bit errors (bits written as '1' will slowly become
255 '0'), which are corrected as far as the ECC is capable of. */
256 static int overwrite_test(void)
260 unsigned max_corrected
= 0;
262 /* We don't expect more than this many correctable bit errors per
265 static unsigned bitstats
[MAXBITS
]; /* bit error histogram. */
267 memset(bitstats
, 0, sizeof(bitstats
));
269 pr_info("overwrite biterrors test\n");
271 for (i
= 0; i
< mtd
->writesize
; i
++)
272 wbuffer
[i
] = hash(i
+seed
);
278 while (opno
< max_overwrite
) {
286 if (err
>= MAXBITS
) {
287 pr_info("Implausible number of bit errors corrected\n");
292 if (err
> max_corrected
) {
294 pr_info("Read reported %d corrected bit errors\n",
297 } else { /* err < 0 */
298 pr_info("Read reported error %d\n", err
);
303 err
= verify_page(0);
305 bitstats
[max_corrected
] = opno
;
306 pr_info("ECC failure, read data is incorrect despite read success\n");
310 err
= mtdtest_relax();
317 /* At this point bitstats[0] contains the number of ops with no bit
318 * errors, bitstats[1] the number of ops with 1 bit error, etc. */
319 pr_info("Bit error histogram (%d operations total):\n", opno
);
320 for (i
= 0; i
< max_corrected
; i
++)
321 pr_info("Page reads with %3d corrected bit errors: %d\n",
328 static int __init
mtd_nandbiterrs_init(void)
333 printk(KERN_INFO
"==================================================\n");
334 pr_info("MTD device: %d\n", dev
);
336 mtd
= get_mtd_device(NULL
, dev
);
339 pr_err("error: cannot get MTD device\n");
343 if (!mtd_type_is_nand(mtd
)) {
344 pr_info("this test requires NAND flash\n");
349 pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
350 (unsigned long long)mtd
->size
, mtd
->erasesize
,
351 mtd
->writesize
, mtd
->oobsize
);
353 subsize
= mtd
->writesize
>> mtd
->subpage_sft
;
354 subcount
= mtd
->writesize
/ subsize
;
356 pr_info("Device uses %d subpages of %d bytes\n", subcount
, subsize
);
358 offset
= (loff_t
)page_offset
* mtd
->writesize
;
359 eraseblock
= mtd_div_by_eb(offset
, mtd
);
361 pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
362 page_offset
, offset
, eraseblock
);
364 wbuffer
= kmalloc(mtd
->writesize
, GFP_KERNEL
);
370 rbuffer
= kmalloc(mtd
->writesize
, GFP_KERNEL
);
376 err
= mtdtest_erase_eraseblock(mtd
, eraseblock
);
381 err
= incremental_errors_test();
383 err
= overwrite_test();
388 /* We leave the block un-erased in case of test failure. */
389 err
= mtdtest_erase_eraseblock(mtd
, eraseblock
);
394 pr_info("finished successfully.\n");
395 printk(KERN_INFO
"==================================================\n");
409 static void __exit
mtd_nandbiterrs_exit(void)
414 module_init(mtd_nandbiterrs_init
);
415 module_exit(mtd_nandbiterrs_exit
);
417 MODULE_DESCRIPTION("NAND bit error recovery test");
418 MODULE_AUTHOR("Iwo Mergler");
419 MODULE_LICENSE("GPL");