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