mtd: tests: stresstest: bail out if device has not enough eraseblocks
[pandora-kernel.git] / drivers / mtd / tests / mtd_oobtest.c
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
51 static inline unsigned int simple_rand(void)
52 {
53         next = next * 1103515245 + 12345;
54         return (unsigned int)((next / 65536) % 32768);
55 }
56
57 static inline void simple_srand(unsigned long seed)
58 {
59         next = seed;
60 }
61
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
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
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
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
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
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
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
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
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
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
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
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
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");