Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[platform/kernel/linux-starfive.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/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
50 static inline unsigned int simple_rand(void)
51 {
52         next = next * 1103515245 + 12345;
53         return (unsigned int)((next / 65536) % 32768);
54 }
55
56 static inline void simple_srand(unsigned long seed)
57 {
58         next = seed;
59 }
60
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
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
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
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
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    = NULL;
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
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
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    = NULL;
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    = NULL;
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
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    = NULL;
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
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
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
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
347         printk(PRINT_PREF "scanning for bad eraseblocks\n");
348         for (i = 0; i < ebcnt; ++i) {
349                 bbt[i] = is_block_bad(i) ? 1 : 0;
350                 if (bbt[i])
351                         bad += 1;
352                 cond_resched();
353         }
354         printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
355         return 0;
356 }
357
358 static int __init mtd_oobtest_init(void)
359 {
360         int err = 0;
361         unsigned int i;
362         uint64_t tmp;
363         struct mtd_oob_ops ops;
364         loff_t addr = 0, addr0;
365
366         printk(KERN_INFO "\n");
367         printk(KERN_INFO "=================================================\n");
368         printk(PRINT_PREF "MTD device: %d\n", dev);
369
370         mtd = get_mtd_device(NULL, dev);
371         if (IS_ERR(mtd)) {
372                 err = PTR_ERR(mtd);
373                 printk(PRINT_PREF "error: cannot get MTD device\n");
374                 return err;
375         }
376
377         if (mtd->type != MTD_NANDFLASH) {
378                 printk(PRINT_PREF "this test requires NAND flash\n");
379                 goto out;
380         }
381
382         tmp = mtd->size;
383         do_div(tmp, mtd->erasesize);
384         ebcnt = tmp;
385         pgcnt = mtd->erasesize / mtd->writesize;
386
387         printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
388                "page size %u, count of eraseblocks %u, pages per "
389                "eraseblock %u, OOB size %u\n",
390                (unsigned long long)mtd->size, mtd->erasesize,
391                mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
392
393         err = -ENOMEM;
394         readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
395         if (!readbuf) {
396                 printk(PRINT_PREF "error: cannot allocate memory\n");
397                 goto out;
398         }
399         writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
400         if (!writebuf) {
401                 printk(PRINT_PREF "error: cannot allocate memory\n");
402                 goto out;
403         }
404
405         err = scan_for_bad_eraseblocks();
406         if (err)
407                 goto out;
408
409         use_offset = 0;
410         use_len = mtd->ecclayout->oobavail;
411         use_len_max = mtd->ecclayout->oobavail;
412         vary_offset = 0;
413
414         /* First test: write all OOB, read it back and verify */
415         printk(PRINT_PREF "test 1 of 5\n");
416
417         err = erase_whole_device();
418         if (err)
419                 goto out;
420
421         simple_srand(1);
422         err = write_whole_device();
423         if (err)
424                 goto out;
425
426         simple_srand(1);
427         err = verify_all_eraseblocks();
428         if (err)
429                 goto out;
430
431         /*
432          * Second test: write all OOB, a block at a time, read it back and
433          * verify.
434          */
435         printk(PRINT_PREF "test 2 of 5\n");
436
437         err = erase_whole_device();
438         if (err)
439                 goto out;
440
441         simple_srand(3);
442         err = write_whole_device();
443         if (err)
444                 goto out;
445
446         /* Check all eraseblocks */
447         simple_srand(3);
448         printk(PRINT_PREF "verifying all eraseblocks\n");
449         for (i = 0; i < ebcnt; ++i) {
450                 if (bbt[i])
451                         continue;
452                 err = verify_eraseblock_in_one_go(i);
453                 if (err)
454                         goto out;
455                 if (i % 256 == 0)
456                         printk(PRINT_PREF "verified up to eraseblock %u\n", i);
457                 cond_resched();
458         }
459         printk(PRINT_PREF "verified %u eraseblocks\n", i);
460
461         /*
462          * Third test: write OOB at varying offsets and lengths, read it back
463          * and verify.
464          */
465         printk(PRINT_PREF "test 3 of 5\n");
466
467         err = erase_whole_device();
468         if (err)
469                 goto out;
470
471         /* Write all eraseblocks */
472         use_offset = 0;
473         use_len = mtd->ecclayout->oobavail;
474         use_len_max = mtd->ecclayout->oobavail;
475         vary_offset = 1;
476         simple_srand(5);
477
478         err = write_whole_device();
479         if (err)
480                 goto out;
481
482         /* Check all eraseblocks */
483         use_offset = 0;
484         use_len = mtd->ecclayout->oobavail;
485         use_len_max = mtd->ecclayout->oobavail;
486         vary_offset = 1;
487         simple_srand(5);
488         err = verify_all_eraseblocks();
489         if (err)
490                 goto out;
491
492         use_offset = 0;
493         use_len = mtd->ecclayout->oobavail;
494         use_len_max = mtd->ecclayout->oobavail;
495         vary_offset = 0;
496
497         /* Fourth test: try to write off end of device */
498         printk(PRINT_PREF "test 4 of 5\n");
499
500         err = erase_whole_device();
501         if (err)
502                 goto out;
503
504         addr0 = 0;
505         for (i = 0; i < ebcnt && bbt[i]; ++i)
506                 addr0 += mtd->erasesize;
507
508         /* Attempt to write off end of OOB */
509         ops.mode      = MTD_OOB_AUTO;
510         ops.len       = 0;
511         ops.retlen    = 0;
512         ops.ooblen    = 1;
513         ops.oobretlen = 0;
514         ops.ooboffs   = mtd->ecclayout->oobavail;
515         ops.datbuf    = NULL;
516         ops.oobbuf    = writebuf;
517         printk(PRINT_PREF "attempting to start write past end of OOB\n");
518         printk(PRINT_PREF "an error is expected...\n");
519         err = mtd->write_oob(mtd, addr0, &ops);
520         if (err) {
521                 printk(PRINT_PREF "error occurred as expected\n");
522                 err = 0;
523         } else {
524                 printk(PRINT_PREF "error: can write past end of OOB\n");
525                 errcnt += 1;
526         }
527
528         /* Attempt to read off end of OOB */
529         ops.mode      = MTD_OOB_AUTO;
530         ops.len       = 0;
531         ops.retlen    = 0;
532         ops.ooblen    = 1;
533         ops.oobretlen = 0;
534         ops.ooboffs   = mtd->ecclayout->oobavail;
535         ops.datbuf    = NULL;
536         ops.oobbuf    = readbuf;
537         printk(PRINT_PREF "attempting to start read past end of OOB\n");
538         printk(PRINT_PREF "an error is expected...\n");
539         err = mtd->read_oob(mtd, addr0, &ops);
540         if (err) {
541                 printk(PRINT_PREF "error occurred as expected\n");
542                 err = 0;
543         } else {
544                 printk(PRINT_PREF "error: can read past end of OOB\n");
545                 errcnt += 1;
546         }
547
548         if (bbt[ebcnt - 1])
549                 printk(PRINT_PREF "skipping end of device tests because last "
550                        "block is bad\n");
551         else {
552                 /* Attempt to write off end of device */
553                 ops.mode      = MTD_OOB_AUTO;
554                 ops.len       = 0;
555                 ops.retlen    = 0;
556                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
557                 ops.oobretlen = 0;
558                 ops.ooboffs   = 0;
559                 ops.datbuf    = NULL;
560                 ops.oobbuf    = writebuf;
561                 printk(PRINT_PREF "attempting to write past end of device\n");
562                 printk(PRINT_PREF "an error is expected...\n");
563                 err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
564                 if (err) {
565                         printk(PRINT_PREF "error occurred as expected\n");
566                         err = 0;
567                 } else {
568                         printk(PRINT_PREF "error: wrote past end of device\n");
569                         errcnt += 1;
570                 }
571
572                 /* Attempt to read off end of device */
573                 ops.mode      = MTD_OOB_AUTO;
574                 ops.len       = 0;
575                 ops.retlen    = 0;
576                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
577                 ops.oobretlen = 0;
578                 ops.ooboffs   = 0;
579                 ops.datbuf    = NULL;
580                 ops.oobbuf    = readbuf;
581                 printk(PRINT_PREF "attempting to read past end of device\n");
582                 printk(PRINT_PREF "an error is expected...\n");
583                 err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
584                 if (err) {
585                         printk(PRINT_PREF "error occurred as expected\n");
586                         err = 0;
587                 } else {
588                         printk(PRINT_PREF "error: read past end of device\n");
589                         errcnt += 1;
590                 }
591
592                 err = erase_eraseblock(ebcnt - 1);
593                 if (err)
594                         goto out;
595
596                 /* Attempt to write off end of device */
597                 ops.mode      = MTD_OOB_AUTO;
598                 ops.len       = 0;
599                 ops.retlen    = 0;
600                 ops.ooblen    = mtd->ecclayout->oobavail;
601                 ops.oobretlen = 0;
602                 ops.ooboffs   = 1;
603                 ops.datbuf    = NULL;
604                 ops.oobbuf    = writebuf;
605                 printk(PRINT_PREF "attempting to write past end of device\n");
606                 printk(PRINT_PREF "an error is expected...\n");
607                 err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
608                 if (err) {
609                         printk(PRINT_PREF "error occurred as expected\n");
610                         err = 0;
611                 } else {
612                         printk(PRINT_PREF "error: wrote past end of device\n");
613                         errcnt += 1;
614                 }
615
616                 /* Attempt to read off end of device */
617                 ops.mode      = MTD_OOB_AUTO;
618                 ops.len       = 0;
619                 ops.retlen    = 0;
620                 ops.ooblen    = mtd->ecclayout->oobavail;
621                 ops.oobretlen = 0;
622                 ops.ooboffs   = 1;
623                 ops.datbuf    = NULL;
624                 ops.oobbuf    = readbuf;
625                 printk(PRINT_PREF "attempting to read past end of device\n");
626                 printk(PRINT_PREF "an error is expected...\n");
627                 err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
628                 if (err) {
629                         printk(PRINT_PREF "error occurred as expected\n");
630                         err = 0;
631                 } else {
632                         printk(PRINT_PREF "error: read past end of device\n");
633                         errcnt += 1;
634                 }
635         }
636
637         /* Fifth test: write / read across block boundaries */
638         printk(PRINT_PREF "test 5 of 5\n");
639
640         /* Erase all eraseblocks */
641         err = erase_whole_device();
642         if (err)
643                 goto out;
644
645         /* Write all eraseblocks */
646         simple_srand(11);
647         printk(PRINT_PREF "writing OOBs of whole device\n");
648         for (i = 0; i < ebcnt - 1; ++i) {
649                 int cnt = 2;
650                 int pg;
651                 size_t sz = mtd->ecclayout->oobavail;
652                 if (bbt[i] || bbt[i + 1])
653                         continue;
654                 addr = (i + 1) * mtd->erasesize - mtd->writesize;
655                 for (pg = 0; pg < cnt; ++pg) {
656                         set_random_data(writebuf, sz);
657                         ops.mode      = MTD_OOB_AUTO;
658                         ops.len       = 0;
659                         ops.retlen    = 0;
660                         ops.ooblen    = sz;
661                         ops.oobretlen = 0;
662                         ops.ooboffs   = 0;
663                         ops.datbuf    = NULL;
664                         ops.oobbuf    = writebuf;
665                         err = mtd->write_oob(mtd, addr, &ops);
666                         if (err)
667                                 goto out;
668                         if (i % 256 == 0)
669                                 printk(PRINT_PREF "written up to eraseblock "
670                                        "%u\n", i);
671                         cond_resched();
672                         addr += mtd->writesize;
673                 }
674         }
675         printk(PRINT_PREF "written %u eraseblocks\n", i);
676
677         /* Check all eraseblocks */
678         simple_srand(11);
679         printk(PRINT_PREF "verifying all eraseblocks\n");
680         for (i = 0; i < ebcnt - 1; ++i) {
681                 if (bbt[i] || bbt[i + 1])
682                         continue;
683                 set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
684                 addr = (i + 1) * mtd->erasesize - mtd->writesize;
685                 ops.mode      = MTD_OOB_AUTO;
686                 ops.len       = 0;
687                 ops.retlen    = 0;
688                 ops.ooblen    = mtd->ecclayout->oobavail * 2;
689                 ops.oobretlen = 0;
690                 ops.ooboffs   = 0;
691                 ops.datbuf    = NULL;
692                 ops.oobbuf    = readbuf;
693                 err = mtd->read_oob(mtd, addr, &ops);
694                 if (err)
695                         goto out;
696                 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
697                         printk(PRINT_PREF "error: verify failed at %#llx\n",
698                                (long long)addr);
699                         errcnt += 1;
700                         if (errcnt > 1000) {
701                                 printk(PRINT_PREF "error: too many errors\n");
702                                 goto out;
703                         }
704                 }
705                 if (i % 256 == 0)
706                         printk(PRINT_PREF "verified up to eraseblock %u\n", i);
707                 cond_resched();
708         }
709         printk(PRINT_PREF "verified %u eraseblocks\n", i);
710
711         printk(PRINT_PREF "finished with %d errors\n", errcnt);
712 out:
713         kfree(bbt);
714         kfree(writebuf);
715         kfree(readbuf);
716         put_mtd_device(mtd);
717         if (err)
718                 printk(PRINT_PREF "error %d occurred\n", err);
719         printk(KERN_INFO "=================================================\n");
720         return err;
721 }
722 module_init(mtd_oobtest_init);
723
724 static void __exit mtd_oobtest_exit(void)
725 {
726         return;
727 }
728 module_exit(mtd_oobtest_exit);
729
730 MODULE_DESCRIPTION("Out-of-band test module");
731 MODULE_AUTHOR("Adrian Hunter");
732 MODULE_LICENSE("GPL");