Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mtd_nandbiterrs.c
Go to the documentation of this file.
1 /*
2  * Copyright © 2012 NetCommWireless
3  * Iwo Mergler <[email protected]>
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  */
42 #include <linux/init.h>
43 #include <linux/module.h>
44 #include <linux/moduleparam.h>
45 #include <linux/mtd/mtd.h>
46 #include <linux/err.h>
47 #include <linux/mtd/nand.h>
48 #include <linux/slab.h>
49 
50 #define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA)
51 
52 static int dev;
53 module_param(dev, int, S_IRUGO);
54 MODULE_PARM_DESC(dev, "MTD device number to use");
55 
56 static unsigned page_offset;
58 MODULE_PARM_DESC(page_offset, "Page number relative to dev start");
59 
60 static unsigned seed;
61 module_param(seed, uint, S_IRUGO);
62 MODULE_PARM_DESC(seed, "Random seed");
63 
64 static int mode;
66 MODULE_PARM_DESC(mode, "0=incremental errors, 1=overwrite test");
67 
68 static unsigned max_overwrite = 10000;
69 
70 static loff_t offset; /* Offset of the page we're using. */
71 static unsigned eraseblock; /* Eraseblock number for our page. */
72 
73 /* We assume that the ECC can correct up to a certain number
74  * of biterrors per subpage. */
75 static unsigned subsize; /* Size of subpages */
76 static unsigned subcount; /* Number of subpages per page */
77 
78 static struct mtd_info *mtd; /* MTD device */
79 
80 static uint8_t *wbuffer; /* One page write / compare buffer */
81 static uint8_t *rbuffer; /* One page read buffer */
82 
83 /* 'random' bytes from known offsets */
84 static uint8_t hash(unsigned offset)
85 {
86  unsigned v = offset;
87  unsigned char c;
88  v ^= 0x7f7edfd3;
89  v = v ^ (v >> 3);
90  v = v ^ (v >> 5);
91  v = v ^ (v >> 13);
92  c = v & 0xFF;
93  /* Reverse bits of result. */
94  c = (c & 0x0F) << 4 | (c & 0xF0) >> 4;
95  c = (c & 0x33) << 2 | (c & 0xCC) >> 2;
96  c = (c & 0x55) << 1 | (c & 0xAA) >> 1;
97  return c;
98 }
99 
100 static int erase_block(void)
101 {
102  int err;
103  struct erase_info ei;
104  loff_t addr = eraseblock * mtd->erasesize;
105 
106  msg("erase_block\n");
107 
108  memset(&ei, 0, sizeof(struct erase_info));
109  ei.mtd = mtd;
110  ei.addr = addr;
111  ei.len = mtd->erasesize;
112 
113  err = mtd_erase(mtd, &ei);
114  if (err || ei.state == MTD_ERASE_FAILED) {
115  msg("error %d while erasing\n", err);
116  if (!err)
117  err = -EIO;
118  return err;
119  }
120 
121  return 0;
122 }
123 
124 /* Writes wbuffer to page */
125 static int write_page(int log)
126 {
127  int err = 0;
128  size_t written;
129 
130  if (log)
131  msg("write_page\n");
132 
133  err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer);
134  if (err || written != mtd->writesize) {
135  msg("error: write failed at %#llx\n", (long long)offset);
136  if (!err)
137  err = -EIO;
138  }
139 
140  return err;
141 }
142 
143 /* Re-writes the data area while leaving the OOB alone. */
144 static int rewrite_page(int log)
145 {
146  int err = 0;
147  struct mtd_oob_ops ops;
148 
149  if (log)
150  msg("rewrite page\n");
151 
152  ops.mode = MTD_OPS_RAW; /* No ECC */
153  ops.len = mtd->writesize;
154  ops.retlen = 0;
155  ops.ooblen = 0;
156  ops.oobretlen = 0;
157  ops.ooboffs = 0;
158  ops.datbuf = wbuffer;
159  ops.oobbuf = NULL;
160 
161  err = mtd_write_oob(mtd, offset, &ops);
162  if (err || ops.retlen != mtd->writesize) {
163  msg("error: write_oob failed (%d)\n", err);
164  if (!err)
165  err = -EIO;
166  }
167 
168  return err;
169 }
170 
171 /* Reads page into rbuffer. Returns number of corrected bit errors (>=0)
172  * or error (<0) */
173 static int read_page(int log)
174 {
175  int err = 0;
176  size_t read;
177  struct mtd_ecc_stats oldstats;
178 
179  if (log)
180  msg("read_page\n");
181 
182  /* Saving last mtd stats */
183  memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
184 
185  err = mtd_read(mtd, offset, mtd->writesize, &read, rbuffer);
186  if (err == -EUCLEAN)
187  err = mtd->ecc_stats.corrected - oldstats.corrected;
188 
189  if (err < 0 || read != mtd->writesize) {
190  msg("error: read failed at %#llx\n", (long long)offset);
191  if (err >= 0)
192  err = -EIO;
193  }
194 
195  return err;
196 }
197 
198 /* Verifies rbuffer against random sequence */
199 static int verify_page(int log)
200 {
201  unsigned i, errs = 0;
202 
203  if (log)
204  msg("verify_page\n");
205 
206  for (i = 0; i < mtd->writesize; i++) {
207  if (rbuffer[i] != hash(i+seed)) {
208  msg("Error: page offset %u, expected %02x, got %02x\n",
209  i, hash(i+seed), rbuffer[i]);
210  errs++;
211  }
212  }
213 
214  if (errs)
215  return -EIO;
216  else
217  return 0;
218 }
219 
220 #define CBIT(v, n) ((v) & (1 << (n)))
221 #define BCLR(v, n) ((v) = (v) & ~(1 << (n)))
222 
223 /* Finds the first '1' bit in wbuffer starting at offset 'byte'
224  * and sets it to '0'. */
225 static int insert_biterror(unsigned byte)
226 {
227  int bit;
228 
229  while (byte < mtd->writesize) {
230  for (bit = 7; bit >= 0; bit--) {
231  if (CBIT(wbuffer[byte], bit)) {
232  BCLR(wbuffer[byte], bit);
233  msg("Inserted biterror @ %u/%u\n", byte, bit);
234  return 0;
235  }
236  }
237  byte++;
238  }
239  msg("biterror: Failed to find a '1' bit\n");
240  return -EIO;
241 }
242 
243 /* Writes 'random' data to page and then introduces deliberate bit
244  * errors into the page, while verifying each step. */
245 static int incremental_errors_test(void)
246 {
247  int err = 0;
248  unsigned i;
249  unsigned errs_per_subpage = 0;
250 
251  msg("incremental biterrors test\n");
252 
253  for (i = 0; i < mtd->writesize; i++)
254  wbuffer[i] = hash(i+seed);
255 
256  err = write_page(1);
257  if (err)
258  goto exit;
259 
260  while (1) {
261 
262  err = rewrite_page(1);
263  if (err)
264  goto exit;
265 
266  err = read_page(1);
267  if (err > 0)
268  msg("Read reported %d corrected bit errors\n", err);
269  if (err < 0) {
270  msg("After %d biterrors per subpage, read reported error %d\n",
271  errs_per_subpage, err);
272  err = 0;
273  goto exit;
274  }
275 
276  err = verify_page(1);
277  if (err) {
278  msg("ECC failure, read data is incorrect despite read success\n");
279  goto exit;
280  }
281 
282  msg("Successfully corrected %d bit errors per subpage\n",
283  errs_per_subpage);
284 
285  for (i = 0; i < subcount; i++) {
286  err = insert_biterror(i * subsize);
287  if (err < 0)
288  goto exit;
289  }
290  errs_per_subpage++;
291  }
292 
293 exit:
294  return err;
295 }
296 
297 
298 /* Writes 'random' data to page and then re-writes that same data repeatedly.
299  This eventually develops bit errors (bits written as '1' will slowly become
300  '0'), which are corrected as far as the ECC is capable of. */
301 static int overwrite_test(void)
302 {
303  int err = 0;
304  unsigned i;
305  unsigned max_corrected = 0;
306  unsigned opno = 0;
307  /* We don't expect more than this many correctable bit errors per
308  * page. */
309  #define MAXBITS 512
310  static unsigned bitstats[MAXBITS]; /* bit error histogram. */
311 
312  memset(bitstats, 0, sizeof(bitstats));
313 
314  msg("overwrite biterrors test\n");
315 
316  for (i = 0; i < mtd->writesize; i++)
317  wbuffer[i] = hash(i+seed);
318 
319  err = write_page(1);
320  if (err)
321  goto exit;
322 
323  while (opno < max_overwrite) {
324 
325  err = rewrite_page(0);
326  if (err)
327  break;
328 
329  err = read_page(0);
330  if (err >= 0) {
331  if (err >= MAXBITS) {
332  msg("Implausible number of bit errors corrected\n");
333  err = -EIO;
334  break;
335  }
336  bitstats[err]++;
337  if (err > max_corrected) {
338  max_corrected = err;
339  msg("Read reported %d corrected bit errors\n",
340  err);
341  }
342  } else { /* err < 0 */
343  msg("Read reported error %d\n", err);
344  err = 0;
345  break;
346  }
347 
348  err = verify_page(0);
349  if (err) {
350  bitstats[max_corrected] = opno;
351  msg("ECC failure, read data is incorrect despite read success\n");
352  break;
353  }
354 
355  opno++;
356  }
357 
358  /* At this point bitstats[0] contains the number of ops with no bit
359  * errors, bitstats[1] the number of ops with 1 bit error, etc. */
360  msg("Bit error histogram (%d operations total):\n", opno);
361  for (i = 0; i < max_corrected; i++)
362  msg("Page reads with %3d corrected bit errors: %d\n",
363  i, bitstats[i]);
364 
365 exit:
366  return err;
367 }
368 
369 static int __init mtd_nandbiterrs_init(void)
370 {
371  int err = 0;
372 
373  msg("\n");
374  msg("==================================================\n");
375  msg("MTD device: %d\n", dev);
376 
377  mtd = get_mtd_device(NULL, dev);
378  if (IS_ERR(mtd)) {
379  err = PTR_ERR(mtd);
380  msg("error: cannot get MTD device\n");
381  goto exit_mtddev;
382  }
383 
384  if (mtd->type != MTD_NANDFLASH) {
385  msg("this test requires NAND flash\n");
386  err = -ENODEV;
387  goto exit_nand;
388  }
389 
390  msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
391  (unsigned long long)mtd->size, mtd->erasesize,
392  mtd->writesize, mtd->oobsize);
393 
394  subsize = mtd->writesize >> mtd->subpage_sft;
395  subcount = mtd->writesize / subsize;
396 
397  msg("Device uses %d subpages of %d bytes\n", subcount, subsize);
398 
399  offset = page_offset * mtd->writesize;
400  eraseblock = mtd_div_by_eb(offset, mtd);
401 
402  msg("Using page=%u, offset=%llu, eraseblock=%u\n",
403  page_offset, offset, eraseblock);
404 
405  wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
406  if (!wbuffer) {
407  err = -ENOMEM;
408  goto exit_wbuffer;
409  }
410 
411  rbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
412  if (!rbuffer) {
413  err = -ENOMEM;
414  goto exit_rbuffer;
415  }
416 
417  err = erase_block();
418  if (err)
419  goto exit_error;
420 
421  if (mode == 0)
422  err = incremental_errors_test();
423  else
424  err = overwrite_test();
425 
426  if (err)
427  goto exit_error;
428 
429  /* We leave the block un-erased in case of test failure. */
430  err = erase_block();
431  if (err)
432  goto exit_error;
433 
434  err = -EIO;
435  msg("finished successfully.\n");
436  msg("==================================================\n");
437 
438 exit_error:
439  kfree(rbuffer);
440 exit_rbuffer:
441  kfree(wbuffer);
442 exit_wbuffer:
443  /* Nothing */
444 exit_nand:
445  put_mtd_device(mtd);
446 exit_mtddev:
447  return err;
448 }
449 
450 static void __exit mtd_nandbiterrs_exit(void)
451 {
452  return;
453 }
454 
455 module_init(mtd_nandbiterrs_init);
456 module_exit(mtd_nandbiterrs_exit);
457 
458 MODULE_DESCRIPTION("NAND bit error recovery test");
459 MODULE_AUTHOR("Iwo Mergler");
460 MODULE_LICENSE("GPL");