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