blob: 5a8c8584112df005cff1d9a393278d6fc322da89 [file] [log] [blame]
Iwo Mergler3cf06f42012-08-31 08:59:48 +10001/*
2 * Copyright © 2012 NetCommWireless
3 * Iwo Mergler <Iwo.Mergler@netcommwireless.com.au>
4 *
5 * Test for multi-bit error recovery on a NAND page This mostly tests the
6 * ECC controller / driver.
7 *
8 * There are two test modes:
9 *
10 * 0 - artificially inserting bit errors until the ECC fails
11 * This is the default method and fairly quick. It should
12 * be independent of the quality of the FLASH.
13 *
14 * 1 - re-writing the same pattern repeatedly until the ECC fails.
15 * This method relies on the physics of NAND FLASH to eventually
16 * generate '0' bits if '1' has been written sufficient times.
17 * Depending on the NAND, the first bit errors will appear after
18 * 1000 or more writes and then will usually snowball, reaching the
19 * limits of the ECC quickly.
20 *
21 * The test stops after 10000 cycles, should your FLASH be
22 * exceptionally good and not generate bit errors before that. Try
23 * a different page in that case.
24 *
25 * Please note that neither of these tests will significantly 'use up' any
26 * FLASH endurance. Only a maximum of two erase operations will be performed.
27 *
28 *
29 * This program is free software; you can redistribute it and/or modify it
30 * under the terms of the GNU General Public License version 2 as published by
31 * the Free Software Foundation.
32 *
33 * This program is distributed in the hope that it will be useful, but WITHOUT
34 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
36 * more details.
37 *
38 * You should have received a copy of the GNU General Public License along with
39 * this program; see the file COPYING. If not, write to the Free Software
40 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 */
Vikram Narayanan600ed672012-10-10 23:04:41 +053042
43#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
44
Iwo Mergler3cf06f42012-08-31 08:59:48 +100045#include <linux/init.h>
46#include <linux/module.h>
47#include <linux/moduleparam.h>
48#include <linux/mtd/mtd.h>
49#include <linux/err.h>
50#include <linux/mtd/nand.h>
51#include <linux/slab.h>
Akinobu Mita56177512013-08-03 18:52:16 +090052#include "mtd_test.h"
Iwo Mergler3cf06f42012-08-31 08:59:48 +100053
Iwo Mergler3cf06f42012-08-31 08:59:48 +100054static int dev;
55module_param(dev, int, S_IRUGO);
56MODULE_PARM_DESC(dev, "MTD device number to use");
57
58static unsigned page_offset;
59module_param(page_offset, uint, S_IRUGO);
60MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
61
62static unsigned seed;
63module_param(seed, uint, S_IRUGO);
64MODULE_PARM_DESC(seed, "Random seed");
65
66static int mode;
67module_param(mode, int, S_IRUGO);
68MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
69
70static unsigned max_overwrite = 10000;
71
72static loff_t offset; /* Offset of the page we're using. */
73static unsigned eraseblock; /* Eraseblock number for our page. */
74
75/* We assume that the ECC can correct up to a certain number
76 * of biterrors per subpage. */
77static unsigned subsize; /* Size of subpages */
78static unsigned subcount; /* Number of subpages per page */
79
80static struct mtd_info *mtd; /* MTD device */
81
82static uint8_t *wbuffer; /* One page write / compare buffer */
83static uint8_t *rbuffer; /* One page read buffer */
84
85/* 'random' bytes from known offsets */
86static uint8_t hash(unsigned offset)
87{
88 unsigned v = offset;
89 unsigned char c;
90 v ^= 0x7f7edfd3;
91 v = v ^ (v >> 3);
92 v = v ^ (v >> 5);
93 v = v ^ (v >> 13);
94 c = v & 0xFF;
95 /* Reverse bits of result. */
96 c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
97 c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
98 c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
99 return c;
100}
101
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000102/* Writes wbuffer to page */
103static int write_page(int log)
104{
Akinobu Mita56177512013-08-03 18:52:16 +0900105 int err;
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000106
107 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530108 pr_info("write_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000109
Akinobu Mita56177512013-08-03 18:52:16 +0900110 err = mtdtest_write(mtd, offset, mtd->writesize, wbuffer);
111 if (err)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530112 pr_err("error: write failed at %#llx\n", (long long)offset);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000113
114 return err;
115}
116
117/* Re-writes the data area while leaving the OOB alone. */
118static int rewrite_page(int log)
119{
120 int err = 0;
121 struct mtd_oob_ops ops;
122
123 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530124 pr_info("rewrite page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000125
126 ops.mode = MTD_OPS_RAW; /* No ECC */
127 ops.len = mtd->writesize;
128 ops.retlen = 0;
129 ops.ooblen = 0;
130 ops.oobretlen = 0;
131 ops.ooboffs = 0;
132 ops.datbuf = wbuffer;
133 ops.oobbuf = NULL;
134
135 err = mtd_write_oob(mtd, offset, &ops);
136 if (err || ops.retlen != mtd->writesize) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530137 pr_err("error: write_oob failed (%d)\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000138 if (!err)
139 err = -EIO;
140 }
141
142 return err;
143}
144
145/* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
146 * or error (<0) */
147static int read_page(int log)
148{
149 int err = 0;
150 size_t read;
151 struct mtd_ecc_stats oldstats;
152
153 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530154 pr_info("read_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000155
156 /* Saving last mtd stats */
157 memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
158
159 err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
160 if (err == -EUCLEAN)
161 err = mtd->ecc_stats.corrected - oldstats.corrected;
162
163 if (err < 0 || read != mtd->writesize) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530164 pr_err("error: read failed at %#llx\n", (long long)offset);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000165 if (err >= 0)
166 err = -EIO;
167 }
168
169 return err;
170}
171
172/* Verifies rbuffer against random sequence */
173static int verify_page(int log)
174{
175 unsigned i, errs = 0;
176
177 if (log)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530178 pr_info("verify_page\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000179
180 for (i = 0; i < mtd->writesize; i++) {
181 if (rbuffer[i] != hash(i+seed)) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530182 pr_err("Error: page offset %u, expected %02x, got %02x\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000183 i, hash(i+seed), rbuffer[i]);
184 errs++;
185 }
186 }
187
188 if (errs)
189 return -EIO;
190 else
191 return 0;
192}
193
194#define CBIT(v, n) ((v) & (1 << (n)))
195#define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
196
197/* Finds the first '1' bit in wbuffer starting at offset 'byte'
198 * and sets it to '0'. */
199static int insert_biterror(unsigned byte)
200{
201 int bit;
202
203 while (byte < mtd->writesize) {
204 for (bit = 7; bit >= 0; bit--) {
205 if (CBIT(wbuffer[byte], bit)) {
206 BCLR(wbuffer[byte], bit);
Vikram Narayanan600ed672012-10-10 23:04:41 +0530207 pr_info("Inserted biterror @ %u/%u\n", byte, bit);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000208 return 0;
209 }
210 }
211 byte++;
212 }
Vikram Narayanan600ed672012-10-10 23:04:41 +0530213 pr_err("biterror: Failed to find a '1' bit\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000214 return -EIO;
215}
216
217/* Writes 'random' data to page and then introduces deliberate bit
218 * errors into the page, while verifying each step. */
219static int incremental_errors_test(void)
220{
221 int err = 0;
222 unsigned i;
223 unsigned errs_per_subpage = 0;
224
Vikram Narayanan600ed672012-10-10 23:04:41 +0530225 pr_info("incremental biterrors test\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000226
227 for (i = 0; i < mtd->writesize; i++)
228 wbuffer[i] = hash(i+seed);
229
230 err = write_page(1);
231 if (err)
232 goto exit;
233
234 while (1) {
235
236 err = rewrite_page(1);
237 if (err)
238 goto exit;
239
240 err = read_page(1);
241 if (err > 0)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530242 pr_info("Read reported %d corrected bit errors\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000243 if (err < 0) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530244 pr_err("After %d biterrors per subpage, read reported error %d\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000245 errs_per_subpage, err);
246 err = 0;
247 goto exit;
248 }
249
250 err = verify_page(1);
251 if (err) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530252 pr_err("ECC failure, read data is incorrect despite read success\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000253 goto exit;
254 }
255
Vikram Narayanan600ed672012-10-10 23:04:41 +0530256 pr_info("Successfully corrected %d bit errors per subpage\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000257 errs_per_subpage);
258
259 for (i = 0; i < subcount; i++) {
260 err = insert_biterror(i * subsize);
261 if (err < 0)
262 goto exit;
263 }
264 errs_per_subpage++;
265 }
266
267exit:
268 return err;
269}
270
271
272/* Writes 'random' data to page and then re-writes that same data repeatedly.
273 This eventually develops bit errors (bits written as '1' will slowly become
274 '0'), which are corrected as far as the ECC is capable of. */
275static int overwrite_test(void)
276{
277 int err = 0;
278 unsigned i;
279 unsigned max_corrected = 0;
280 unsigned opno = 0;
281 /* We don't expect more than this many correctable bit errors per
282 * page. */
283 #define MAXBITS 512
284 static unsigned bitstats[MAXBITS]; /* bit error histogram. */
285
286 memset(bitstats, 0, sizeof(bitstats));
287
Vikram Narayanan600ed672012-10-10 23:04:41 +0530288 pr_info("overwrite biterrors test\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000289
290 for (i = 0; i < mtd->writesize; i++)
291 wbuffer[i] = hash(i+seed);
292
293 err = write_page(1);
294 if (err)
295 goto exit;
296
297 while (opno < max_overwrite) {
298
299 err = rewrite_page(0);
300 if (err)
301 break;
302
303 err = read_page(0);
304 if (err >= 0) {
305 if (err >= MAXBITS) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530306 pr_info("Implausible number of bit errors corrected\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000307 err = -EIO;
308 break;
309 }
310 bitstats[err]++;
311 if (err > max_corrected) {
312 max_corrected = err;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530313 pr_info("Read reported %d corrected bit errors\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000314 err);
315 }
316 } else { /* err < 0 */
Vikram Narayanan600ed672012-10-10 23:04:41 +0530317 pr_info("Read reported error %d\n", err);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000318 err = 0;
319 break;
320 }
321
322 err = verify_page(0);
323 if (err) {
324 bitstats[max_corrected] = opno;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530325 pr_info("ECC failure, read data is incorrect despite read success\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000326 break;
327 }
328
329 opno++;
330 }
331
332 /* At this point bitstats[0] contains the number of ops with no bit
333 * errors, bitstats[1] the number of ops with 1 bit error, etc. */
Vikram Narayanan600ed672012-10-10 23:04:41 +0530334 pr_info("Bit error histogram (%d operations total):\n", opno);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000335 for (i = 0; i < max_corrected; i++)
Vikram Narayanan600ed672012-10-10 23:04:41 +0530336 pr_info("Page reads with %3d corrected bit errors: %d\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000337 i, bitstats[i]);
338
339exit:
340 return err;
341}
342
343static int __init mtd_nandbiterrs_init(void)
344{
345 int err = 0;
346
Vikram Narayanan600ed672012-10-10 23:04:41 +0530347 printk("\n");
348 printk(KERN_INFO "==================================================\n");
349 pr_info("MTD device: %d\n", dev);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000350
351 mtd = get_mtd_device(NULL, dev);
352 if (IS_ERR(mtd)) {
353 err = PTR_ERR(mtd);
Vikram Narayanan600ed672012-10-10 23:04:41 +0530354 pr_err("error: cannot get MTD device\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000355 goto exit_mtddev;
356 }
357
358 if (mtd->type != MTD_NANDFLASH) {
Vikram Narayanan600ed672012-10-10 23:04:41 +0530359 pr_info("this test requires NAND flash\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000360 err = -ENODEV;
361 goto exit_nand;
362 }
363
Vikram Narayanan600ed672012-10-10 23:04:41 +0530364 pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000365 (unsigned long long)mtd->size, mtd->erasesize,
366 mtd->writesize, mtd->oobsize);
367
368 subsize = mtd->writesize >> mtd->subpage_sft;
369 subcount = mtd->writesize / subsize;
370
Vikram Narayanan600ed672012-10-10 23:04:41 +0530371 pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000372
373 offset = page_offset * mtd->writesize;
374 eraseblock = mtd_div_by_eb(offset, mtd);
375
Vikram Narayanan600ed672012-10-10 23:04:41 +0530376 pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000377 page_offset, offset, eraseblock);
378
379 wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
380 if (!wbuffer) {
381 err = -ENOMEM;
382 goto exit_wbuffer;
383 }
384
385 rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
386 if (!rbuffer) {
387 err = -ENOMEM;
388 goto exit_rbuffer;
389 }
390
Akinobu Mita56177512013-08-03 18:52:16 +0900391 err = mtdtest_erase_eraseblock(mtd, eraseblock);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000392 if (err)
393 goto exit_error;
394
395 if (mode == 0)
396 err = incremental_errors_test();
397 else
398 err = overwrite_test();
399
400 if (err)
401 goto exit_error;
402
403 /* We leave the block un-erased in case of test failure. */
Akinobu Mita56177512013-08-03 18:52:16 +0900404 err = mtdtest_erase_eraseblock(mtd, eraseblock);
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000405 if (err)
406 goto exit_error;
407
408 err = -EIO;
Vikram Narayanan600ed672012-10-10 23:04:41 +0530409 pr_info("finished successfully.\n");
410 printk(KERN_INFO "==================================================\n");
Iwo Mergler3cf06f42012-08-31 08:59:48 +1000411
412exit_error:
413 kfree(rbuffer);
414exit_rbuffer:
415 kfree(wbuffer);
416exit_wbuffer:
417 /* Nothing */
418exit_nand:
419 put_mtd_device(mtd);
420exit_mtddev:
421 return err;
422}
423
424static void __exit mtd_nandbiterrs_exit(void)
425{
426 return;
427}
428
429module_init(mtd_nandbiterrs_init);
430module_exit(mtd_nandbiterrs_exit);
431
432MODULE_DESCRIPTION("NAND bit error recovery test");
433MODULE_AUTHOR("Iwo Mergler");
434MODULE_LICENSE("GPL");