• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2008 Nokia Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; see the file COPYING. If not, write to the Free Software
15  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  *
17  * Test OOB read and write on MTD device.
18  *
19  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
20  */
21 
22 #include <asm/div64.h>
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/moduleparam.h>
26 #include <linux/err.h>
27 #include <linux/mtd/mtd.h>
28 #include <linux/sched.h>
29 
30 #define PRINT_PREF KERN_INFO "mtd_oobtest: "
31 
32 static int dev;
33 module_param(dev, int, S_IRUGO);
34 MODULE_PARM_DESC(dev, "MTD device number to use");
35 
36 static struct mtd_info *mtd;
37 static unsigned char *readbuf;
38 static unsigned char *writebuf;
39 static unsigned char *bbt;
40 
41 static int ebcnt;
42 static int pgcnt;
43 static int errcnt;
44 static int use_offset;
45 static int use_len;
46 static int use_len_max;
47 static int vary_offset;
48 static unsigned long next = 1;
49 
simple_rand(void)50 static inline unsigned int simple_rand(void)
51 {
52 	next = next * 1103515245 + 12345;
53 	return (unsigned int)((next / 65536) % 32768);
54 }
55 
simple_srand(unsigned long seed)56 static inline void simple_srand(unsigned long seed)
57 {
58 	next = seed;
59 }
60 
set_random_data(unsigned char * buf,size_t len)61 static void set_random_data(unsigned char *buf, size_t len)
62 {
63 	size_t i;
64 
65 	for (i = 0; i < len; ++i)
66 		buf[i] = simple_rand();
67 }
68 
erase_eraseblock(int ebnum)69 static int erase_eraseblock(int ebnum)
70 {
71 	int err;
72 	struct erase_info ei;
73 	loff_t addr = ebnum * mtd->erasesize;
74 
75 	memset(&ei, 0, sizeof(struct erase_info));
76 	ei.mtd  = mtd;
77 	ei.addr = addr;
78 	ei.len  = mtd->erasesize;
79 
80 	err = mtd->erase(mtd, &ei);
81 	if (err) {
82 		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
83 		return err;
84 	}
85 
86 	if (ei.state == MTD_ERASE_FAILED) {
87 		printk(PRINT_PREF "some erase error occurred at EB %d\n",
88 		       ebnum);
89 		return -EIO;
90 	}
91 
92 	return 0;
93 }
94 
erase_whole_device(void)95 static int erase_whole_device(void)
96 {
97 	int err;
98 	unsigned int i;
99 
100 	printk(PRINT_PREF "erasing whole device\n");
101 	for (i = 0; i < ebcnt; ++i) {
102 		if (bbt[i])
103 			continue;
104 		err = erase_eraseblock(i);
105 		if (err)
106 			return err;
107 		cond_resched();
108 	}
109 	printk(PRINT_PREF "erased %u eraseblocks\n", i);
110 	return 0;
111 }
112 
do_vary_offset(void)113 static void do_vary_offset(void)
114 {
115 	use_len -= 1;
116 	if (use_len < 1) {
117 		use_offset += 1;
118 		if (use_offset >= use_len_max)
119 			use_offset = 0;
120 		use_len = use_len_max - use_offset;
121 	}
122 }
123 
write_eraseblock(int ebnum)124 static int write_eraseblock(int ebnum)
125 {
126 	int i;
127 	struct mtd_oob_ops ops;
128 	int err = 0;
129 	loff_t addr = ebnum * mtd->erasesize;
130 
131 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
132 		set_random_data(writebuf, use_len);
133 		ops.mode      = MTD_OOB_AUTO;
134 		ops.len       = 0;
135 		ops.retlen    = 0;
136 		ops.ooblen    = use_len;
137 		ops.oobretlen = 0;
138 		ops.ooboffs   = use_offset;
139 		ops.datbuf    = 0;
140 		ops.oobbuf    = writebuf;
141 		err = mtd->write_oob(mtd, addr, &ops);
142 		if (err || ops.oobretlen != use_len) {
143 			printk(PRINT_PREF "error: writeoob failed at %#llx\n",
144 			       (long long)addr);
145 			printk(PRINT_PREF "error: use_len %d, use_offset %d\n",
146 			       use_len, use_offset);
147 			errcnt += 1;
148 			return err ? err : -1;
149 		}
150 		if (vary_offset)
151 			do_vary_offset();
152 	}
153 
154 	return err;
155 }
156 
write_whole_device(void)157 static int write_whole_device(void)
158 {
159 	int err;
160 	unsigned int i;
161 
162 	printk(PRINT_PREF "writing OOBs of whole device\n");
163 	for (i = 0; i < ebcnt; ++i) {
164 		if (bbt[i])
165 			continue;
166 		err = write_eraseblock(i);
167 		if (err)
168 			return err;
169 		if (i % 256 == 0)
170 			printk(PRINT_PREF "written up to eraseblock %u\n", i);
171 		cond_resched();
172 	}
173 	printk(PRINT_PREF "written %u eraseblocks\n", i);
174 	return 0;
175 }
176 
verify_eraseblock(int ebnum)177 static int verify_eraseblock(int ebnum)
178 {
179 	int i;
180 	struct mtd_oob_ops ops;
181 	int err = 0;
182 	loff_t addr = ebnum * mtd->erasesize;
183 
184 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
185 		set_random_data(writebuf, use_len);
186 		ops.mode      = MTD_OOB_AUTO;
187 		ops.len       = 0;
188 		ops.retlen    = 0;
189 		ops.ooblen    = use_len;
190 		ops.oobretlen = 0;
191 		ops.ooboffs   = use_offset;
192 		ops.datbuf    = 0;
193 		ops.oobbuf    = readbuf;
194 		err = mtd->read_oob(mtd, addr, &ops);
195 		if (err || ops.oobretlen != use_len) {
196 			printk(PRINT_PREF "error: readoob failed at %#llx\n",
197 			       (long long)addr);
198 			errcnt += 1;
199 			return err ? err : -1;
200 		}
201 		if (memcmp(readbuf, writebuf, use_len)) {
202 			printk(PRINT_PREF "error: verify failed at %#llx\n",
203 			       (long long)addr);
204 			errcnt += 1;
205 			if (errcnt > 1000) {
206 				printk(PRINT_PREF "error: too many errors\n");
207 				return -1;
208 			}
209 		}
210 		if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
211 			int k;
212 
213 			ops.mode      = MTD_OOB_AUTO;
214 			ops.len       = 0;
215 			ops.retlen    = 0;
216 			ops.ooblen    = mtd->ecclayout->oobavail;
217 			ops.oobretlen = 0;
218 			ops.ooboffs   = 0;
219 			ops.datbuf    = 0;
220 			ops.oobbuf    = readbuf;
221 			err = mtd->read_oob(mtd, addr, &ops);
222 			if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
223 				printk(PRINT_PREF "error: readoob failed at "
224 				       "%#llx\n", (long long)addr);
225 				errcnt += 1;
226 				return err ? err : -1;
227 			}
228 			if (memcmp(readbuf + use_offset, writebuf, use_len)) {
229 				printk(PRINT_PREF "error: verify failed at "
230 				       "%#llx\n", (long long)addr);
231 				errcnt += 1;
232 				if (errcnt > 1000) {
233 					printk(PRINT_PREF "error: too many "
234 					       "errors\n");
235 					return -1;
236 				}
237 			}
238 			for (k = 0; k < use_offset; ++k)
239 				if (readbuf[k] != 0xff) {
240 					printk(PRINT_PREF "error: verify 0xff "
241 					       "failed at %#llx\n",
242 					       (long long)addr);
243 					errcnt += 1;
244 					if (errcnt > 1000) {
245 						printk(PRINT_PREF "error: too "
246 						       "many errors\n");
247 						return -1;
248 					}
249 				}
250 			for (k = use_offset + use_len;
251 			     k < mtd->ecclayout->oobavail; ++k)
252 				if (readbuf[k] != 0xff) {
253 					printk(PRINT_PREF "error: verify 0xff "
254 					       "failed at %#llx\n",
255 					       (long long)addr);
256 					errcnt += 1;
257 					if (errcnt > 1000) {
258 						printk(PRINT_PREF "error: too "
259 						       "many errors\n");
260 						return -1;
261 					}
262 				}
263 		}
264 		if (vary_offset)
265 			do_vary_offset();
266 	}
267 	return err;
268 }
269 
verify_eraseblock_in_one_go(int ebnum)270 static int verify_eraseblock_in_one_go(int ebnum)
271 {
272 	struct mtd_oob_ops ops;
273 	int err = 0;
274 	loff_t addr = ebnum * mtd->erasesize;
275 	size_t len = mtd->ecclayout->oobavail * pgcnt;
276 
277 	set_random_data(writebuf, len);
278 	ops.mode      = MTD_OOB_AUTO;
279 	ops.len       = 0;
280 	ops.retlen    = 0;
281 	ops.ooblen    = len;
282 	ops.oobretlen = 0;
283 	ops.ooboffs   = 0;
284 	ops.datbuf    = 0;
285 	ops.oobbuf    = readbuf;
286 	err = mtd->read_oob(mtd, addr, &ops);
287 	if (err || ops.oobretlen != len) {
288 		printk(PRINT_PREF "error: readoob failed at %#llx\n",
289 		       (long long)addr);
290 		errcnt += 1;
291 		return err ? err : -1;
292 	}
293 	if (memcmp(readbuf, writebuf, len)) {
294 		printk(PRINT_PREF "error: verify failed at %#llx\n",
295 		       (long long)addr);
296 		errcnt += 1;
297 		if (errcnt > 1000) {
298 			printk(PRINT_PREF "error: too many errors\n");
299 			return -1;
300 		}
301 	}
302 
303 	return err;
304 }
305 
verify_all_eraseblocks(void)306 static int verify_all_eraseblocks(void)
307 {
308 	int err;
309 	unsigned int i;
310 
311 	printk(PRINT_PREF "verifying all eraseblocks\n");
312 	for (i = 0; i < ebcnt; ++i) {
313 		if (bbt[i])
314 			continue;
315 		err = verify_eraseblock(i);
316 		if (err)
317 			return err;
318 		if (i % 256 == 0)
319 			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
320 		cond_resched();
321 	}
322 	printk(PRINT_PREF "verified %u eraseblocks\n", i);
323 	return 0;
324 }
325 
is_block_bad(int ebnum)326 static int is_block_bad(int ebnum)
327 {
328 	int ret;
329 	loff_t addr = ebnum * mtd->erasesize;
330 
331 	ret = mtd->block_isbad(mtd, addr);
332 	if (ret)
333 		printk(PRINT_PREF "block %d is bad\n", ebnum);
334 	return ret;
335 }
336 
scan_for_bad_eraseblocks(void)337 static int scan_for_bad_eraseblocks(void)
338 {
339 	int i, bad = 0;
340 
341 	bbt = kmalloc(ebcnt, GFP_KERNEL);
342 	if (!bbt) {
343 		printk(PRINT_PREF "error: cannot allocate memory\n");
344 		return -ENOMEM;
345 	}
346 	memset(bbt, 0 , ebcnt);
347 
348 	printk(PRINT_PREF "scanning for bad eraseblocks\n");
349 	for (i = 0; i < ebcnt; ++i) {
350 		bbt[i] = is_block_bad(i) ? 1 : 0;
351 		if (bbt[i])
352 			bad += 1;
353 		cond_resched();
354 	}
355 	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
356 	return 0;
357 }
358 
mtd_oobtest_init(void)359 static int __init mtd_oobtest_init(void)
360 {
361 	int err = 0;
362 	unsigned int i;
363 	uint64_t tmp;
364 	struct mtd_oob_ops ops;
365 	loff_t addr = 0, addr0;
366 
367 	printk(KERN_INFO "\n");
368 	printk(KERN_INFO "=================================================\n");
369 	printk(PRINT_PREF "MTD device: %d\n", dev);
370 
371 	mtd = get_mtd_device(NULL, dev);
372 	if (IS_ERR(mtd)) {
373 		err = PTR_ERR(mtd);
374 		printk(PRINT_PREF "error: cannot get MTD device\n");
375 		return err;
376 	}
377 
378 	if (mtd->type != MTD_NANDFLASH) {
379 		printk(PRINT_PREF "this test requires NAND flash\n");
380 		goto out;
381 	}
382 
383 	tmp = mtd->size;
384 	do_div(tmp, mtd->erasesize);
385 	ebcnt = tmp;
386 	pgcnt = mtd->erasesize / mtd->writesize;
387 
388 	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
389 	       "page size %u, count of eraseblocks %u, pages per "
390 	       "eraseblock %u, OOB size %u\n",
391 	       (unsigned long long)mtd->size, mtd->erasesize,
392 	       mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
393 
394 	err = -ENOMEM;
395 	mtd->erasesize = mtd->erasesize;
396 	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
397 	if (!readbuf) {
398 		printk(PRINT_PREF "error: cannot allocate memory\n");
399 		goto out;
400 	}
401 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
402 	if (!writebuf) {
403 		printk(PRINT_PREF "error: cannot allocate memory\n");
404 		goto out;
405 	}
406 
407 	err = scan_for_bad_eraseblocks();
408 	if (err)
409 		goto out;
410 
411 	use_offset = 0;
412 	use_len = mtd->ecclayout->oobavail;
413 	use_len_max = mtd->ecclayout->oobavail;
414 	vary_offset = 0;
415 
416 	/* First test: write all OOB, read it back and verify */
417 	printk(PRINT_PREF "test 1 of 5\n");
418 
419 	err = erase_whole_device();
420 	if (err)
421 		goto out;
422 
423 	simple_srand(1);
424 	err = write_whole_device();
425 	if (err)
426 		goto out;
427 
428 	simple_srand(1);
429 	err = verify_all_eraseblocks();
430 	if (err)
431 		goto out;
432 
433 	/*
434 	 * Second test: write all OOB, a block at a time, read it back and
435 	 * verify.
436 	 */
437 	printk(PRINT_PREF "test 2 of 5\n");
438 
439 	err = erase_whole_device();
440 	if (err)
441 		goto out;
442 
443 	simple_srand(3);
444 	err = write_whole_device();
445 	if (err)
446 		goto out;
447 
448 	/* Check all eraseblocks */
449 	simple_srand(3);
450 	printk(PRINT_PREF "verifying all eraseblocks\n");
451 	for (i = 0; i < ebcnt; ++i) {
452 		if (bbt[i])
453 			continue;
454 		err = verify_eraseblock_in_one_go(i);
455 		if (err)
456 			goto out;
457 		if (i % 256 == 0)
458 			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
459 		cond_resched();
460 	}
461 	printk(PRINT_PREF "verified %u eraseblocks\n", i);
462 
463 	/*
464 	 * Third test: write OOB at varying offsets and lengths, read it back
465 	 * and verify.
466 	 */
467 	printk(PRINT_PREF "test 3 of 5\n");
468 
469 	err = erase_whole_device();
470 	if (err)
471 		goto out;
472 
473 	/* Write all eraseblocks */
474 	use_offset = 0;
475 	use_len = mtd->ecclayout->oobavail;
476 	use_len_max = mtd->ecclayout->oobavail;
477 	vary_offset = 1;
478 	simple_srand(5);
479 	printk(PRINT_PREF "writing OOBs of whole device\n");
480 	for (i = 0; i < ebcnt; ++i) {
481 		if (bbt[i])
482 			continue;
483 		err = write_eraseblock(i);
484 		if (err)
485 			goto out;
486 		if (i % 256 == 0)
487 			printk(PRINT_PREF "written up to eraseblock %u\n", i);
488 		cond_resched();
489 	}
490 	printk(PRINT_PREF "written %u eraseblocks\n", i);
491 
492 	/* Check all eraseblocks */
493 	use_offset = 0;
494 	use_len = mtd->ecclayout->oobavail;
495 	use_len_max = mtd->ecclayout->oobavail;
496 	vary_offset = 1;
497 	simple_srand(5);
498 	err = verify_all_eraseblocks();
499 	if (err)
500 		goto out;
501 
502 	use_offset = 0;
503 	use_len = mtd->ecclayout->oobavail;
504 	use_len_max = mtd->ecclayout->oobavail;
505 	vary_offset = 0;
506 
507 	/* Fourth test: try to write off end of device */
508 	printk(PRINT_PREF "test 4 of 5\n");
509 
510 	err = erase_whole_device();
511 	if (err)
512 		goto out;
513 
514 	addr0 = 0;
515 	for (i = 0; bbt[i] && i < ebcnt; ++i)
516 		addr0 += mtd->erasesize;
517 
518 	/* Attempt to write off end of OOB */
519 	ops.mode      = MTD_OOB_AUTO;
520 	ops.len       = 0;
521 	ops.retlen    = 0;
522 	ops.ooblen    = 1;
523 	ops.oobretlen = 0;
524 	ops.ooboffs   = mtd->ecclayout->oobavail;
525 	ops.datbuf    = 0;
526 	ops.oobbuf    = writebuf;
527 	printk(PRINT_PREF "attempting to start write past end of OOB\n");
528 	printk(PRINT_PREF "an error is expected...\n");
529 	err = mtd->write_oob(mtd, addr0, &ops);
530 	if (err) {
531 		printk(PRINT_PREF "error occurred as expected\n");
532 		err = 0;
533 	} else {
534 		printk(PRINT_PREF "error: can write past end of OOB\n");
535 		errcnt += 1;
536 	}
537 
538 	/* Attempt to read off end of OOB */
539 	ops.mode      = MTD_OOB_AUTO;
540 	ops.len       = 0;
541 	ops.retlen    = 0;
542 	ops.ooblen    = 1;
543 	ops.oobretlen = 0;
544 	ops.ooboffs   = mtd->ecclayout->oobavail;
545 	ops.datbuf    = 0;
546 	ops.oobbuf    = readbuf;
547 	printk(PRINT_PREF "attempting to start read past end of OOB\n");
548 	printk(PRINT_PREF "an error is expected...\n");
549 	err = mtd->read_oob(mtd, addr0, &ops);
550 	if (err) {
551 		printk(PRINT_PREF "error occurred as expected\n");
552 		err = 0;
553 	} else {
554 		printk(PRINT_PREF "error: can read past end of OOB\n");
555 		errcnt += 1;
556 	}
557 
558 	if (bbt[ebcnt - 1])
559 		printk(PRINT_PREF "skipping end of device tests because last "
560 		       "block is bad\n");
561 	else {
562 		/* Attempt to write off end of device */
563 		ops.mode      = MTD_OOB_AUTO;
564 		ops.len       = 0;
565 		ops.retlen    = 0;
566 		ops.ooblen    = mtd->ecclayout->oobavail + 1;
567 		ops.oobretlen = 0;
568 		ops.ooboffs   = 0;
569 		ops.datbuf    = 0;
570 		ops.oobbuf    = writebuf;
571 		printk(PRINT_PREF "attempting to write past end of device\n");
572 		printk(PRINT_PREF "an error is expected...\n");
573 		err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
574 		if (err) {
575 			printk(PRINT_PREF "error occurred as expected\n");
576 			err = 0;
577 		} else {
578 			printk(PRINT_PREF "error: wrote past end of device\n");
579 			errcnt += 1;
580 		}
581 
582 		/* Attempt to read off end of device */
583 		ops.mode      = MTD_OOB_AUTO;
584 		ops.len       = 0;
585 		ops.retlen    = 0;
586 		ops.ooblen    = mtd->ecclayout->oobavail + 1;
587 		ops.oobretlen = 0;
588 		ops.ooboffs   = 0;
589 		ops.datbuf    = 0;
590 		ops.oobbuf    = readbuf;
591 		printk(PRINT_PREF "attempting to read past end of device\n");
592 		printk(PRINT_PREF "an error is expected...\n");
593 		err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
594 		if (err) {
595 			printk(PRINT_PREF "error occurred as expected\n");
596 			err = 0;
597 		} else {
598 			printk(PRINT_PREF "error: read past end of device\n");
599 			errcnt += 1;
600 		}
601 
602 		err = erase_eraseblock(ebcnt - 1);
603 		if (err)
604 			goto out;
605 
606 		/* Attempt to write off end of device */
607 		ops.mode      = MTD_OOB_AUTO;
608 		ops.len       = 0;
609 		ops.retlen    = 0;
610 		ops.ooblen    = mtd->ecclayout->oobavail;
611 		ops.oobretlen = 0;
612 		ops.ooboffs   = 1;
613 		ops.datbuf    = 0;
614 		ops.oobbuf    = writebuf;
615 		printk(PRINT_PREF "attempting to write past end of device\n");
616 		printk(PRINT_PREF "an error is expected...\n");
617 		err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
618 		if (err) {
619 			printk(PRINT_PREF "error occurred as expected\n");
620 			err = 0;
621 		} else {
622 			printk(PRINT_PREF "error: wrote past end of device\n");
623 			errcnt += 1;
624 		}
625 
626 		/* Attempt to read off end of device */
627 		ops.mode      = MTD_OOB_AUTO;
628 		ops.len       = 0;
629 		ops.retlen    = 0;
630 		ops.ooblen    = mtd->ecclayout->oobavail;
631 		ops.oobretlen = 0;
632 		ops.ooboffs   = 1;
633 		ops.datbuf    = 0;
634 		ops.oobbuf    = readbuf;
635 		printk(PRINT_PREF "attempting to read past end of device\n");
636 		printk(PRINT_PREF "an error is expected...\n");
637 		err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
638 		if (err) {
639 			printk(PRINT_PREF "error occurred as expected\n");
640 			err = 0;
641 		} else {
642 			printk(PRINT_PREF "error: read past end of device\n");
643 			errcnt += 1;
644 		}
645 	}
646 
647 	/* Fifth test: write / read across block boundaries */
648 	printk(PRINT_PREF "test 5 of 5\n");
649 
650 	/* Erase all eraseblocks */
651 	err = erase_whole_device();
652 	if (err)
653 		goto out;
654 
655 	/* Write all eraseblocks */
656 	simple_srand(11);
657 	printk(PRINT_PREF "writing OOBs of whole device\n");
658 	for (i = 0; i < ebcnt - 1; ++i) {
659 		int cnt = 2;
660 		int pg;
661 		size_t sz = mtd->ecclayout->oobavail;
662 		if (bbt[i] || bbt[i + 1])
663 			continue;
664 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
665 		for (pg = 0; pg < cnt; ++pg) {
666 			set_random_data(writebuf, sz);
667 			ops.mode      = MTD_OOB_AUTO;
668 			ops.len       = 0;
669 			ops.retlen    = 0;
670 			ops.ooblen    = sz;
671 			ops.oobretlen = 0;
672 			ops.ooboffs   = 0;
673 			ops.datbuf    = 0;
674 			ops.oobbuf    = writebuf;
675 			err = mtd->write_oob(mtd, addr, &ops);
676 			if (err)
677 				goto out;
678 			if (i % 256 == 0)
679 				printk(PRINT_PREF "written up to eraseblock "
680 				       "%u\n", i);
681 			cond_resched();
682 			addr += mtd->writesize;
683 		}
684 	}
685 	printk(PRINT_PREF "written %u eraseblocks\n", i);
686 
687 	/* Check all eraseblocks */
688 	simple_srand(11);
689 	printk(PRINT_PREF "verifying all eraseblocks\n");
690 	for (i = 0; i < ebcnt - 1; ++i) {
691 		if (bbt[i] || bbt[i + 1])
692 			continue;
693 		set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
694 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
695 		ops.mode      = MTD_OOB_AUTO;
696 		ops.len       = 0;
697 		ops.retlen    = 0;
698 		ops.ooblen    = mtd->ecclayout->oobavail * 2;
699 		ops.oobretlen = 0;
700 		ops.ooboffs   = 0;
701 		ops.datbuf    = 0;
702 		ops.oobbuf    = readbuf;
703 		err = mtd->read_oob(mtd, addr, &ops);
704 		if (err)
705 			goto out;
706 		if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
707 			printk(PRINT_PREF "error: verify failed at %#llx\n",
708 			       (long long)addr);
709 			errcnt += 1;
710 			if (errcnt > 1000) {
711 				printk(PRINT_PREF "error: too many errors\n");
712 				goto out;
713 			}
714 		}
715 		if (i % 256 == 0)
716 			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
717 		cond_resched();
718 	}
719 	printk(PRINT_PREF "verified %u eraseblocks\n", i);
720 
721 	printk(PRINT_PREF "finished with %d errors\n", errcnt);
722 out:
723 	kfree(bbt);
724 	kfree(writebuf);
725 	kfree(readbuf);
726 	put_mtd_device(mtd);
727 	if (err)
728 		printk(PRINT_PREF "error %d occurred\n", err);
729 	printk(KERN_INFO "=================================================\n");
730 	return err;
731 }
732 module_init(mtd_oobtest_init);
733 
mtd_oobtest_exit(void)734 static void __exit mtd_oobtest_exit(void)
735 {
736 	return;
737 }
738 module_exit(mtd_oobtest_exit);
739 
740 MODULE_DESCRIPTION("Out-of-band test module");
741 MODULE_AUTHOR("Adrian Hunter");
742 MODULE_LICENSE("GPL");
743