blob: 08084c018a59a8863de361e1f9631a8c8b36df0a [file] [log] [blame]
Thomas Gleixner4cd10352019-05-29 16:57:41 -07001// SPDX-License-Identifier: GPL-2.0-only
Iwo Mergler3cf06f42012-08-31 08:59:48 +10002/*
3 * Copyright © 2012 NetCommWireless
4 * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
5 *
6 * Test for multi-bit error recovery on a NAND page This mostly tests the
7 * ECC controller / driver.
8 *
9 * There are two test modes:
10 *
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.
14 *
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.
21 *
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.
25 *
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.
Iwo Mergler3cf06f42012-08-31 08:59:48 +100028 */
Vikram Narayanan600ed672012-10-10 23:04:41 +053029
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
Iwo Mergler3cf06f42012-08-31 08:59:48 +100032#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>
Boris Brezillond4092d72017-08-04 17:29:10 +020037#include <linux/mtd/rawnand.h>
Iwo Mergler3cf06f42012-08-31 08:59:48 +100038#include <linux/slab.h>
Akinobu Mita56177512013-08-03 18:52:16 +090039#include "mtd_test.h"
Iwo Mergler3cf06f42012-08-31 08:59:48 +100040
Iwo Mergler3cf06f42012-08-31 08:59:48 +100041static int dev;
42module_param(dev, int, S_IRUGO);
43MODULE_PARM_DESC(dev, "MTD device number to use");
44
45static unsigned page_offset;
46module_param(page_offset, uint, S_IRUGO);
47MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
48
49static unsigned seed;
50module_param(seed, uint, S_IRUGO);
51MODULE_PARM_DESC(seed, "Random seed");
52
53static int mode;
54module_param(mode, int, S_IRUGO);
55MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
56
57static unsigned max_overwrite = 10000;
58
59static loff_t offset; /* Offset of the page we're using. */
60static unsigned eraseblock; /* Eraseblock number for our page. */
61
62/* We assume that the ECC can correct up to a certain number
63 * of biterrors per subpage. */
64static unsigned subsize; /* Size of subpages */
65static unsigned subcount; /* Number of subpages per page */
66
67static struct mtd_info *mtd; /* MTD device */
68
69static uint8_t *wbuffer; /* One page write / compare buffer */
70static uint8_t *rbuffer; /* One page read buffer */
71
72/* 'random' bytes from known offsets */
73static uint8_t hash(unsigned offset)
74{
75 unsigned v = offset;
76 unsigned char c;
77 v ^= 0x7f7edfd3;
78 v = v ^ (v >> 3);
79 v = v ^ (v >> 5);
80 v = v ^ (v >> 13);
81 c = v & 0xFF;
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;
86 return c;
87}
88
Iwo Mergler3cf06f42012-08-31 08:59:48 +100089/* Writes wbuffer to page */
90static int write_page(int log)
91{
Iwo Mergler3cf06f42012-08-31 08:59:48 +100092 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +053093 pr_info("write_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +100094
Akinobu Mita8a9f4aa2013-08-15 22:55:09 +090095 return mtdtest_write(mtd, offset, mtd->writesize, wbuffer);
Iwo Mergler3cf06f42012-08-31 08:59:48 +100096}
97
98/* Re-writes the data area while leaving the OOB alone. */
99static int rewrite_page(int log)
100{
101 int err = 0;
102 struct mtd_oob_ops ops;
103
104 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530105 pr_info("rewrite page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000106
107 ops.mode = MTD_OPS_RAW; /* No ECC */
108 ops.len = mtd->writesize;
109 ops.retlen = 0;
110 ops.ooblen = 0;
111 ops.oobretlen = 0;
112 ops.ooboffs = 0;
113 ops.datbuf = wbuffer;
114 ops.oobbuf = NULL;
115
116 err = mtd_write_oob(mtd, offset, &ops);
117 if (err || ops.retlen != mtd->writesize) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530118 pr_err("error: write_oob failed (%d)\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000119 if (!err)
120 err = -EIO;
121 }
122
123 return err;
124}
125
126/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
127 * or error (<0) */
128static int read_page(int log)
129{
130 int err = 0;
131 size_t read;
132 struct mtd_ecc_stats oldstats;
133
134 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530135 pr_info("read_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000136
137 /* Saving last mtd stats */
138 memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
139
140 err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
Sascha Hauer6cbefbd2018-01-09 10:47:02 +0100141 if (!err || err == -EUCLEAN)
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000142 err = mtd->ecc_stats.corrected - oldstats.corrected;
143
144 if (err < 0 || read != mtd->writesize) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530145 pr_err("error: read failed at %#llx\n", (long long)offset);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000146 if (err >= 0)
147 err = -EIO;
148 }
149
150 return err;
151}
152
153/* Verifies rbuffer against random sequence */
154static int verify_page(int log)
155{
156 unsigned i, errs = 0;
157
158 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530159 pr_info("verify_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000160
161 for (i = 0; i < mtd->writesize; i++) {
162 if (rbuffer[i] != hash(i+seed)) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530163 pr_err("Error: page offset %u, expected %02x, got %02x\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000164 i, hash(i+seed), rbuffer[i]);
165 errs++;
166 }
167 }
168
169 if (errs)
170 return -EIO;
171 else
172 return 0;
173}
174
175#define CBIT(v, n) ((v) & (1 << (n)))
176#define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
177
178/* Finds the first '1' bit in wbuffer starting at offset 'byte'
179 * and sets it to '0'. */
180static int insert_biterror(unsigned byte)
181{
182 int bit;
183
184 while (byte < mtd->writesize) {
185 for (bit = 7; bit >= 0; bit--) {
186 if (CBIT(wbuffer[byte], bit)) {
187 BCLR(wbuffer[byte], bit);
Vikram Narayanan600ed672012-10-10 23:04:41 +0530188 pr_info("Inserted biterror @ %u/%u\n", byte, bit);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000189 return 0;
190 }
191 }
192 byte++;
193 }
Vikram Narayanan600ed672012-10-10 23:04:41 +0530194 pr_err("biterror: Failed to find a '1' bit\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000195 return -EIO;
196}
197
198/* Writes 'random' data to page and then introduces deliberate bit
199 * errors into the page, while verifying each step. */
200static int incremental_errors_test(void)
201{
202 int err = 0;
203 unsigned i;
204 unsigned errs_per_subpage = 0;
205
Vikram Narayanan600ed672012-10-10 23:04:41 +0530206 pr_info("incremental biterrors test\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000207
208 for (i = 0; i < mtd->writesize; i++)
209 wbuffer[i] = hash(i+seed);
210
211 err = write_page(1);
212 if (err)
213 goto exit;
214
215 while (1) {
216
217 err = rewrite_page(1);
218 if (err)
219 goto exit;
220
221 err = read_page(1);
222 if (err > 0)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530223 pr_info("Read reported %d corrected bit errors\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000224 if (err < 0) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530225 pr_err("After %d biterrors per subpage, read reported error %d\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000226 errs_per_subpage, err);
227 err = 0;
228 goto exit;
229 }
230
231 err = verify_page(1);
232 if (err) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530233 pr_err("ECC failure, read data is incorrect despite read success\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000234 goto exit;
235 }
236
Vikram Narayanan600ed672012-10-10 23:04:41 +0530237 pr_info("Successfully corrected %d bit errors per subpage\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000238 errs_per_subpage);
239
240 for (i = 0; i < subcount; i++) {
241 err = insert_biterror(i * subsize);
242 if (err < 0)
243 goto exit;
244 }
245 errs_per_subpage++;
246 }
247
248exit:
249 return err;
250}
251
252
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. */
256static int overwrite_test(void)
257{
258 int err = 0;
259 unsigned i;
260 unsigned max_corrected = 0;
261 unsigned opno = 0;
262 /* We don't expect more than this many correctable bit errors per
263 * page. */
264 #define MAXBITS 512
265 static unsigned bitstats[MAXBITS]; /* bit error histogram. */
266
267 memset(bitstats, 0, sizeof(bitstats));
268
Vikram Narayanan600ed672012-10-10 23:04:41 +0530269 pr_info("overwrite biterrors test\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000270
271 for (i = 0; i < mtd->writesize; i++)
272 wbuffer[i] = hash(i+seed);
273
274 err = write_page(1);
275 if (err)
276 goto exit;
277
278 while (opno < max_overwrite) {
279
Iwo Mergler97b67132016-05-11 16:54:57 +1000280 err = write_page(0);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000281 if (err)
282 break;
283
284 err = read_page(0);
285 if (err >= 0) {
286 if (err >= MAXBITS) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530287 pr_info("Implausible number of bit errors corrected\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000288 err = -EIO;
289 break;
290 }
291 bitstats[err]++;
292 if (err > max_corrected) {
293 max_corrected = err;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530294 pr_info("Read reported %d corrected bit errors\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000295 err);
296 }
297 } else { /* err < 0 */
Vikram Narayanan600ed672012-10-10 23:04:41 +0530298 pr_info("Read reported error %d\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000299 err = 0;
300 break;
301 }
302
303 err = verify_page(0);
304 if (err) {
305 bitstats[max_corrected] = opno;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530306 pr_info("ECC failure, read data is incorrect despite read success\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000307 break;
308 }
309
Richard Weinberger2a6a28e72015-03-29 21:52:06 +0200310 err = mtdtest_relax();
311 if (err)
312 break;
313
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000314 opno++;
315 }
316
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. */
Vikram Narayanan600ed672012-10-10 23:04:41 +0530319 pr_info("Bit error histogram (%d operations total):\n", opno);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000320 for (i = 0; i < max_corrected; i++)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530321 pr_info("Page reads with %3d corrected bit errors: %d\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000322 i, bitstats[i]);
323
324exit:
325 return err;
326}
327
328static int __init mtd_nandbiterrs_init(void)
329{
330 int err = 0;
331
Vikram Narayanan600ed672012-10-10 23:04:41 +0530332 printk("\n");
333 printk(KERN_INFO "==================================================\n");
334 pr_info("MTD device: %d\n", dev);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000335
336 mtd = get_mtd_device(NULL, dev);
337 if (IS_ERR(mtd)) {
338 err = PTR_ERR(mtd);
Vikram Narayanan600ed672012-10-10 23:04:41 +0530339 pr_err("error: cannot get MTD device\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000340 goto exit_mtddev;
341 }
342
Huang Shijie818b9732013-09-25 14:58:17 +0800343 if (!mtd_type_is_nand(mtd)) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530344 pr_info("this test requires NAND flash\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000345 err = -ENODEV;
346 goto exit_nand;
347 }
348
Vikram Narayanan600ed672012-10-10 23:04:41 +0530349 pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000350 (unsigned long long)mtd->size, mtd->erasesize,
351 mtd->writesize, mtd->oobsize);
352
353 subsize = mtd->writesize >> mtd->subpage_sft;
354 subcount = mtd->writesize / subsize;
355
Vikram Narayanan600ed672012-10-10 23:04:41 +0530356 pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000357
Brian Norris1001ff7a2014-07-21 19:07:12 -0700358 offset = (loff_t)page_offset * mtd->writesize;
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000359 eraseblock = mtd_div_by_eb(offset, mtd);
360
Vikram Narayanan600ed672012-10-10 23:04:41 +0530361 pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000362 page_offset, offset, eraseblock);
363
364 wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
365 if (!wbuffer) {
366 err = -ENOMEM;
367 goto exit_wbuffer;
368 }
369
370 rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
371 if (!rbuffer) {
372 err = -ENOMEM;
373 goto exit_rbuffer;
374 }
375
Akinobu Mita56177512013-08-03 18:52:16 +0900376 err = mtdtest_erase_eraseblock(mtd, eraseblock);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000377 if (err)
378 goto exit_error;
379
380 if (mode == 0)
381 err = incremental_errors_test();
382 else
383 err = overwrite_test();
384
385 if (err)
386 goto exit_error;
387
388 /* We leave the block un-erased in case of test failure. */
Akinobu Mita56177512013-08-03 18:52:16 +0900389 err = mtdtest_erase_eraseblock(mtd, eraseblock);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000390 if (err)
391 goto exit_error;
392
393 err = -EIO;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530394 pr_info("finished successfully.\n");
395 printk(KERN_INFO "==================================================\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000396
397exit_error:
398 kfree(rbuffer);
399exit_rbuffer:
400 kfree(wbuffer);
401exit_wbuffer:
402 /* Nothing */
403exit_nand:
404 put_mtd_device(mtd);
405exit_mtddev:
406 return err;
407}
408
409static void __exit mtd_nandbiterrs_exit(void)
410{
411 return;
412}
413
414module_init(mtd_nandbiterrs_init);
415module_exit(mtd_nandbiterrs_exit);
416
417MODULE_DESCRIPTION("NAND bit error recovery test");
418MODULE_AUTHOR("Iwo Mergler");
419MODULE_LICENSE("GPL");