mtd: mtd_oobtest: Fix bitflip_limit usage in test case 3
[firefly-linux-kernel-4.4.55.git] / 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                 cond_resched();
116         }
117         pr_info("written %u eraseblocks\n", i);
118         return 0;
119 }
120
121 /*
122  * Display the address, offset and data bytes at comparison failure.
123  * Return number of bitflips encountered.
124  */
125 static size_t memcmpshow(loff_t addr, const void *cs, const void *ct, size_t count)
126 {
127         const unsigned char *su1, *su2;
128         int res;
129         size_t i = 0;
130         size_t bitflips = 0;
131
132         for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--, i++) {
133                 res = *su1 ^ *su2;
134                 if (res) {
135                         pr_info("error @addr[0x%lx:0x%zx] 0x%x -> 0x%x diff 0x%x\n",
136                                 (unsigned long)addr, i, *su1, *su2, res);
137                         bitflips += hweight8(res);
138                 }
139         }
140
141         return bitflips;
142 }
143
144 /*
145  * Compare with 0xff and show the address, offset and data bytes at
146  * comparison failure. Return number of bitflips encountered.
147  */
148 static size_t memffshow(loff_t addr, loff_t offset, const void *cs,
149                         size_t count)
150 {
151         const unsigned char *su1;
152         int res;
153         size_t i = 0;
154         size_t bitflips = 0;
155
156         for (su1 = cs; 0 < count; ++su1, count--, i++) {
157                 res = *su1 ^ 0xff;
158                 if (res) {
159                         pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0xff diff 0x%x\n",
160                                 (unsigned long)addr, (unsigned long)offset + i,
161                                 *su1, res);
162                         bitflips += hweight8(res);
163                 }
164         }
165
166         return bitflips;
167 }
168
169 static int verify_eraseblock(int ebnum)
170 {
171         int i;
172         struct mtd_oob_ops ops;
173         int err = 0;
174         loff_t addr = (loff_t)ebnum * mtd->erasesize;
175         size_t bitflips;
176
177         prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
178         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
179                 ops.mode      = MTD_OPS_AUTO_OOB;
180                 ops.len       = 0;
181                 ops.retlen    = 0;
182                 ops.ooblen    = use_len;
183                 ops.oobretlen = 0;
184                 ops.ooboffs   = use_offset;
185                 ops.datbuf    = NULL;
186                 ops.oobbuf    = readbuf;
187                 err = mtd_read_oob(mtd, addr, &ops);
188                 if (err || ops.oobretlen != use_len) {
189                         pr_err("error: readoob failed at %#llx\n",
190                                (long long)addr);
191                         errcnt += 1;
192                         return err ? err : -1;
193                 }
194
195                 bitflips = memcmpshow(addr, readbuf,
196                                       writebuf + (use_len_max * i) + use_offset,
197                                       use_len);
198                 if (bitflips > bitflip_limit) {
199                         pr_err("error: verify failed at %#llx\n",
200                                (long long)addr);
201                         errcnt += 1;
202                         if (errcnt > 1000) {
203                                 pr_err("error: too many errors\n");
204                                 return -1;
205                         }
206                 } else if (bitflips) {
207                         pr_info("ignoring error as within bitflip_limit\n");
208                 }
209
210                 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
211                         int k;
212
213                         ops.mode      = MTD_OPS_AUTO_OOB;
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                                 pr_err("error: readoob failed at %#llx\n",
224                                                 (long long)addr);
225                                 errcnt += 1;
226                                 return err ? err : -1;
227                         }
228                         bitflips = memcmpshow(addr, readbuf + use_offset,
229                                               writebuf + (use_len_max * i) + use_offset,
230                                               use_len);
231
232                         /* verify pre-offset area for 0xff */
233                         bitflips += memffshow(addr, 0, readbuf, use_offset);
234
235                         /* verify post-(use_offset + use_len) area for 0xff */
236                         k = use_offset + use_len;
237                         bitflips += memffshow(addr, k, readbuf + k,
238                                               mtd->ecclayout->oobavail - k);
239
240                         if (bitflips > bitflip_limit) {
241                                 pr_err("error: verify failed at %#llx\n",
242                                                 (long long)addr);
243                                 errcnt += 1;
244                                 if (errcnt > 1000) {
245                                         pr_err("error: too many errors\n");
246                                         return -1;
247                                 }
248                         } else if (bitflips) {
249                                 pr_info("ignoring errors as within bitflip limit\n");
250                         }
251                 }
252                 if (vary_offset)
253                         do_vary_offset();
254         }
255         return err;
256 }
257
258 static int verify_eraseblock_in_one_go(int ebnum)
259 {
260         struct mtd_oob_ops ops;
261         int err = 0;
262         loff_t addr = (loff_t)ebnum * mtd->erasesize;
263         size_t len = mtd->ecclayout->oobavail * pgcnt;
264         size_t oobavail = mtd->ecclayout->oobavail;
265         size_t bitflips;
266         int i;
267
268         prandom_bytes_state(&rnd_state, writebuf, len);
269         ops.mode      = MTD_OPS_AUTO_OOB;
270         ops.len       = 0;
271         ops.retlen    = 0;
272         ops.ooblen    = len;
273         ops.oobretlen = 0;
274         ops.ooboffs   = 0;
275         ops.datbuf    = NULL;
276         ops.oobbuf    = readbuf;
277
278         /* read entire block's OOB at one go */
279         err = mtd_read_oob(mtd, addr, &ops);
280         if (err || ops.oobretlen != len) {
281                 pr_err("error: readoob failed at %#llx\n",
282                        (long long)addr);
283                 errcnt += 1;
284                 return err ? err : -1;
285         }
286
287         /* verify one page OOB at a time for bitflip per page limit check */
288         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
289                 bitflips = memcmpshow(addr, readbuf + (i * oobavail),
290                                       writebuf + (i * oobavail), oobavail);
291                 if (bitflips > bitflip_limit) {
292                         pr_err("error: verify failed at %#llx\n",
293                                (long long)addr);
294                         errcnt += 1;
295                         if (errcnt > 1000) {
296                                 pr_err("error: too many errors\n");
297                                 return -1;
298                         }
299                 } else if (bitflips) {
300                         pr_info("ignoring error as within bitflip_limit\n");
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         pr_info("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                         pr_info("verified up to eraseblock %u\n", i);
321                 cond_resched();
322         }
323         pr_info("verified %u eraseblocks\n", i);
324         return 0;
325 }
326
327 static int __init mtd_oobtest_init(void)
328 {
329         int err = 0;
330         unsigned int i;
331         uint64_t tmp;
332         struct mtd_oob_ops ops;
333         loff_t addr = 0, addr0;
334
335         printk(KERN_INFO "\n");
336         printk(KERN_INFO "=================================================\n");
337
338         if (dev < 0) {
339                 pr_info("Please specify a valid mtd-device via module parameter\n");
340                 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
341                 return -EINVAL;
342         }
343
344         pr_info("MTD device: %d\n", dev);
345
346         mtd = get_mtd_device(NULL, dev);
347         if (IS_ERR(mtd)) {
348                 err = PTR_ERR(mtd);
349                 pr_err("error: cannot get MTD device\n");
350                 return err;
351         }
352
353         if (!mtd_type_is_nand(mtd)) {
354                 pr_info("this test requires NAND flash\n");
355                 goto out;
356         }
357
358         tmp = mtd->size;
359         do_div(tmp, mtd->erasesize);
360         ebcnt = tmp;
361         pgcnt = mtd->erasesize / mtd->writesize;
362
363         pr_info("MTD device size %llu, eraseblock size %u, "
364                "page size %u, count of eraseblocks %u, pages per "
365                "eraseblock %u, OOB size %u\n",
366                (unsigned long long)mtd->size, mtd->erasesize,
367                mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
368
369         err = -ENOMEM;
370         readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
371         if (!readbuf)
372                 goto out;
373         writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
374         if (!writebuf)
375                 goto out;
376         bbt = kzalloc(ebcnt, GFP_KERNEL);
377         if (!bbt)
378                 goto out;
379
380         err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
381         if (err)
382                 goto out;
383
384         use_offset = 0;
385         use_len = mtd->ecclayout->oobavail;
386         use_len_max = mtd->ecclayout->oobavail;
387         vary_offset = 0;
388
389         /* First test: write all OOB, read it back and verify */
390         pr_info("test 1 of 5\n");
391
392         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
393         if (err)
394                 goto out;
395
396         prandom_seed_state(&rnd_state, 1);
397         err = write_whole_device();
398         if (err)
399                 goto out;
400
401         prandom_seed_state(&rnd_state, 1);
402         err = verify_all_eraseblocks();
403         if (err)
404                 goto out;
405
406         /*
407          * Second test: write all OOB, a block at a time, read it back and
408          * verify.
409          */
410         pr_info("test 2 of 5\n");
411
412         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
413         if (err)
414                 goto out;
415
416         prandom_seed_state(&rnd_state, 3);
417         err = write_whole_device();
418         if (err)
419                 goto out;
420
421         /* Check all eraseblocks */
422         prandom_seed_state(&rnd_state, 3);
423         pr_info("verifying all eraseblocks\n");
424         for (i = 0; i < ebcnt; ++i) {
425                 if (bbt[i])
426                         continue;
427                 err = verify_eraseblock_in_one_go(i);
428                 if (err)
429                         goto out;
430                 if (i % 256 == 0)
431                         pr_info("verified up to eraseblock %u\n", i);
432                 cond_resched();
433         }
434         pr_info("verified %u eraseblocks\n", i);
435
436         /*
437          * Third test: write OOB at varying offsets and lengths, read it back
438          * and verify.
439          */
440         pr_info("test 3 of 5\n");
441
442         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
443         if (err)
444                 goto out;
445
446         /* Write all eraseblocks */
447         use_offset = 0;
448         use_len = mtd->ecclayout->oobavail;
449         use_len_max = mtd->ecclayout->oobavail;
450         vary_offset = 1;
451         prandom_seed_state(&rnd_state, 5);
452
453         err = write_whole_device();
454         if (err)
455                 goto out;
456
457         /* Check all eraseblocks */
458         use_offset = 0;
459         use_len = mtd->ecclayout->oobavail;
460         use_len_max = mtd->ecclayout->oobavail;
461         vary_offset = 1;
462         prandom_seed_state(&rnd_state, 5);
463         err = verify_all_eraseblocks();
464         if (err)
465                 goto out;
466
467         use_offset = 0;
468         use_len = mtd->ecclayout->oobavail;
469         use_len_max = mtd->ecclayout->oobavail;
470         vary_offset = 0;
471
472         /* Fourth test: try to write off end of device */
473         pr_info("test 4 of 5\n");
474
475         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
476         if (err)
477                 goto out;
478
479         addr0 = 0;
480         for (i = 0; i < ebcnt && bbt[i]; ++i)
481                 addr0 += mtd->erasesize;
482
483         /* Attempt to write off end of OOB */
484         ops.mode      = MTD_OPS_AUTO_OOB;
485         ops.len       = 0;
486         ops.retlen    = 0;
487         ops.ooblen    = 1;
488         ops.oobretlen = 0;
489         ops.ooboffs   = mtd->ecclayout->oobavail;
490         ops.datbuf    = NULL;
491         ops.oobbuf    = writebuf;
492         pr_info("attempting to start write past end of OOB\n");
493         pr_info("an error is expected...\n");
494         err = mtd_write_oob(mtd, addr0, &ops);
495         if (err) {
496                 pr_info("error occurred as expected\n");
497                 err = 0;
498         } else {
499                 pr_err("error: can write past end of OOB\n");
500                 errcnt += 1;
501         }
502
503         /* Attempt to read off end of OOB */
504         ops.mode      = MTD_OPS_AUTO_OOB;
505         ops.len       = 0;
506         ops.retlen    = 0;
507         ops.ooblen    = 1;
508         ops.oobretlen = 0;
509         ops.ooboffs   = mtd->ecclayout->oobavail;
510         ops.datbuf    = NULL;
511         ops.oobbuf    = readbuf;
512         pr_info("attempting to start read past end of OOB\n");
513         pr_info("an error is expected...\n");
514         err = mtd_read_oob(mtd, addr0, &ops);
515         if (err) {
516                 pr_info("error occurred as expected\n");
517                 err = 0;
518         } else {
519                 pr_err("error: can read past end of OOB\n");
520                 errcnt += 1;
521         }
522
523         if (bbt[ebcnt - 1])
524                 pr_info("skipping end of device tests because last "
525                        "block is bad\n");
526         else {
527                 /* Attempt to write off end of device */
528                 ops.mode      = MTD_OPS_AUTO_OOB;
529                 ops.len       = 0;
530                 ops.retlen    = 0;
531                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
532                 ops.oobretlen = 0;
533                 ops.ooboffs   = 0;
534                 ops.datbuf    = NULL;
535                 ops.oobbuf    = writebuf;
536                 pr_info("attempting to write past end of device\n");
537                 pr_info("an error is expected...\n");
538                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
539                 if (err) {
540                         pr_info("error occurred as expected\n");
541                         err = 0;
542                 } else {
543                         pr_err("error: wrote past end of device\n");
544                         errcnt += 1;
545                 }
546
547                 /* Attempt to read off end of device */
548                 ops.mode      = MTD_OPS_AUTO_OOB;
549                 ops.len       = 0;
550                 ops.retlen    = 0;
551                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
552                 ops.oobretlen = 0;
553                 ops.ooboffs   = 0;
554                 ops.datbuf    = NULL;
555                 ops.oobbuf    = readbuf;
556                 pr_info("attempting to read past end of device\n");
557                 pr_info("an error is expected...\n");
558                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
559                 if (err) {
560                         pr_info("error occurred as expected\n");
561                         err = 0;
562                 } else {
563                         pr_err("error: read past end of device\n");
564                         errcnt += 1;
565                 }
566
567                 err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
568                 if (err)
569                         goto out;
570
571                 /* Attempt to write off end of device */
572                 ops.mode      = MTD_OPS_AUTO_OOB;
573                 ops.len       = 0;
574                 ops.retlen    = 0;
575                 ops.ooblen    = mtd->ecclayout->oobavail;
576                 ops.oobretlen = 0;
577                 ops.ooboffs   = 1;
578                 ops.datbuf    = NULL;
579                 ops.oobbuf    = writebuf;
580                 pr_info("attempting to write past end of device\n");
581                 pr_info("an error is expected...\n");
582                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
583                 if (err) {
584                         pr_info("error occurred as expected\n");
585                         err = 0;
586                 } else {
587                         pr_err("error: wrote past end of device\n");
588                         errcnt += 1;
589                 }
590
591                 /* Attempt to read off end of device */
592                 ops.mode      = MTD_OPS_AUTO_OOB;
593                 ops.len       = 0;
594                 ops.retlen    = 0;
595                 ops.ooblen    = mtd->ecclayout->oobavail;
596                 ops.oobretlen = 0;
597                 ops.ooboffs   = 1;
598                 ops.datbuf    = NULL;
599                 ops.oobbuf    = readbuf;
600                 pr_info("attempting to read past end of device\n");
601                 pr_info("an error is expected...\n");
602                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
603                 if (err) {
604                         pr_info("error occurred as expected\n");
605                         err = 0;
606                 } else {
607                         pr_err("error: read past end of device\n");
608                         errcnt += 1;
609                 }
610         }
611
612         /* Fifth test: write / read across block boundaries */
613         pr_info("test 5 of 5\n");
614
615         /* Erase all eraseblocks */
616         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
617         if (err)
618                 goto out;
619
620         /* Write all eraseblocks */
621         prandom_seed_state(&rnd_state, 11);
622         pr_info("writing OOBs of whole device\n");
623         for (i = 0; i < ebcnt - 1; ++i) {
624                 int cnt = 2;
625                 int pg;
626                 size_t sz = mtd->ecclayout->oobavail;
627                 if (bbt[i] || bbt[i + 1])
628                         continue;
629                 addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
630                 prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
631                 for (pg = 0; pg < cnt; ++pg) {
632                         ops.mode      = MTD_OPS_AUTO_OOB;
633                         ops.len       = 0;
634                         ops.retlen    = 0;
635                         ops.ooblen    = sz;
636                         ops.oobretlen = 0;
637                         ops.ooboffs   = 0;
638                         ops.datbuf    = NULL;
639                         ops.oobbuf    = writebuf + pg * sz;
640                         err = mtd_write_oob(mtd, addr, &ops);
641                         if (err)
642                                 goto out;
643                         if (i % 256 == 0)
644                                 pr_info("written up to eraseblock %u\n", i);
645                         cond_resched();
646                         addr += mtd->writesize;
647                 }
648         }
649         pr_info("written %u eraseblocks\n", i);
650
651         /* Check all eraseblocks */
652         prandom_seed_state(&rnd_state, 11);
653         pr_info("verifying all eraseblocks\n");
654         for (i = 0; i < ebcnt - 1; ++i) {
655                 if (bbt[i] || bbt[i + 1])
656                         continue;
657                 prandom_bytes_state(&rnd_state, writebuf,
658                                         mtd->ecclayout->oobavail * 2);
659                 addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
660                 ops.mode      = MTD_OPS_AUTO_OOB;
661                 ops.len       = 0;
662                 ops.retlen    = 0;
663                 ops.ooblen    = mtd->ecclayout->oobavail * 2;
664                 ops.oobretlen = 0;
665                 ops.ooboffs   = 0;
666                 ops.datbuf    = NULL;
667                 ops.oobbuf    = readbuf;
668                 err = mtd_read_oob(mtd, addr, &ops);
669                 if (err)
670                         goto out;
671                 if (memcmpshow(addr, readbuf, writebuf,
672                                mtd->ecclayout->oobavail * 2)) {
673                         pr_err("error: verify failed at %#llx\n",
674                                (long long)addr);
675                         errcnt += 1;
676                         if (errcnt > 1000) {
677                                 pr_err("error: too many errors\n");
678                                 goto out;
679                         }
680                 }
681                 if (i % 256 == 0)
682                         pr_info("verified up to eraseblock %u\n", i);
683                 cond_resched();
684         }
685         pr_info("verified %u eraseblocks\n", i);
686
687         pr_info("finished with %d errors\n", errcnt);
688 out:
689         kfree(bbt);
690         kfree(writebuf);
691         kfree(readbuf);
692         put_mtd_device(mtd);
693         if (err)
694                 pr_info("error %d occurred\n", err);
695         printk(KERN_INFO "=================================================\n");
696         return err;
697 }
698 module_init(mtd_oobtest_init);
699
700 static void __exit mtd_oobtest_exit(void)
701 {
702         return;
703 }
704 module_exit(mtd_oobtest_exit);
705
706 MODULE_DESCRIPTION("Out-of-band test module");
707 MODULE_AUTHOR("Adrian Hunter");
708 MODULE_LICENSE("GPL");