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