mtd: mtd_oobtest: generate consistent data for verification
[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 module_param(dev, int, S_IRUGO);
38 MODULE_PARM_DESC(dev, "MTD device number to use");
39
40 static struct mtd_info *mtd;
41 static unsigned char *readbuf;
42 static unsigned char *writebuf;
43 static unsigned char *bbt;
44
45 static int ebcnt;
46 static int pgcnt;
47 static int errcnt;
48 static int use_offset;
49 static int use_len;
50 static int use_len_max;
51 static int vary_offset;
52 static struct rnd_state rnd_state;
53
54 static void do_vary_offset(void)
55 {
56         use_len -= 1;
57         if (use_len < 1) {
58                 use_offset += 1;
59                 if (use_offset >= use_len_max)
60                         use_offset = 0;
61                 use_len = use_len_max - use_offset;
62         }
63 }
64
65 static int write_eraseblock(int ebnum)
66 {
67         int i;
68         struct mtd_oob_ops ops;
69         int err = 0;
70         loff_t addr = ebnum * mtd->erasesize;
71
72         prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
73         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
74                 ops.mode      = MTD_OPS_AUTO_OOB;
75                 ops.len       = 0;
76                 ops.retlen    = 0;
77                 ops.ooblen    = use_len;
78                 ops.oobretlen = 0;
79                 ops.ooboffs   = use_offset;
80                 ops.datbuf    = NULL;
81                 ops.oobbuf    = writebuf + (use_len_max * i) + use_offset;
82                 err = mtd_write_oob(mtd, addr, &ops);
83                 if (err || ops.oobretlen != use_len) {
84                         pr_err("error: writeoob failed at %#llx\n",
85                                (long long)addr);
86                         pr_err("error: use_len %d, use_offset %d\n",
87                                use_len, use_offset);
88                         errcnt += 1;
89                         return err ? err : -1;
90                 }
91                 if (vary_offset)
92                         do_vary_offset();
93         }
94
95         return err;
96 }
97
98 static int write_whole_device(void)
99 {
100         int err;
101         unsigned int i;
102
103         pr_info("writing OOBs of whole device\n");
104         for (i = 0; i < ebcnt; ++i) {
105                 if (bbt[i])
106                         continue;
107                 err = write_eraseblock(i);
108                 if (err)
109                         return err;
110                 if (i % 256 == 0)
111                         pr_info("written up to eraseblock %u\n", i);
112                 cond_resched();
113         }
114         pr_info("written %u eraseblocks\n", i);
115         return 0;
116 }
117
118 static int verify_eraseblock(int ebnum)
119 {
120         int i;
121         struct mtd_oob_ops ops;
122         int err = 0;
123         loff_t addr = ebnum * mtd->erasesize;
124
125         prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
126         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
127                 ops.mode      = MTD_OPS_AUTO_OOB;
128                 ops.len       = 0;
129                 ops.retlen    = 0;
130                 ops.ooblen    = use_len;
131                 ops.oobretlen = 0;
132                 ops.ooboffs   = use_offset;
133                 ops.datbuf    = NULL;
134                 ops.oobbuf    = readbuf;
135                 err = mtd_read_oob(mtd, addr, &ops);
136                 if (err || ops.oobretlen != use_len) {
137                         pr_err("error: readoob failed at %#llx\n",
138                                (long long)addr);
139                         errcnt += 1;
140                         return err ? err : -1;
141                 }
142                 if (memcmp(readbuf, writebuf + (use_len_max * i) + use_offset,
143                            use_len)) {
144                         pr_err("error: verify failed at %#llx\n",
145                                (long long)addr);
146                         errcnt += 1;
147                         if (errcnt > 1000) {
148                                 pr_err("error: too many errors\n");
149                                 return -1;
150                         }
151                 }
152                 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
153                         int k;
154
155                         ops.mode      = MTD_OPS_AUTO_OOB;
156                         ops.len       = 0;
157                         ops.retlen    = 0;
158                         ops.ooblen    = mtd->ecclayout->oobavail;
159                         ops.oobretlen = 0;
160                         ops.ooboffs   = 0;
161                         ops.datbuf    = NULL;
162                         ops.oobbuf    = readbuf;
163                         err = mtd_read_oob(mtd, addr, &ops);
164                         if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
165                                 pr_err("error: readoob failed at %#llx\n",
166                                                 (long long)addr);
167                                 errcnt += 1;
168                                 return err ? err : -1;
169                         }
170                         if (memcmp(readbuf + use_offset,
171                                    writebuf + (use_len_max * i) + use_offset,
172                                    use_len)) {
173                                 pr_err("error: verify failed at %#llx\n",
174                                                 (long long)addr);
175                                 errcnt += 1;
176                                 if (errcnt > 1000) {
177                                         pr_err("error: too many errors\n");
178                                         return -1;
179                                 }
180                         }
181                         for (k = 0; k < use_offset; ++k)
182                                 if (readbuf[k] != 0xff) {
183                                         pr_err("error: verify 0xff "
184                                                "failed at %#llx\n",
185                                                (long long)addr);
186                                         errcnt += 1;
187                                         if (errcnt > 1000) {
188                                                 pr_err("error: too "
189                                                        "many errors\n");
190                                                 return -1;
191                                         }
192                                 }
193                         for (k = use_offset + use_len;
194                              k < mtd->ecclayout->oobavail; ++k)
195                                 if (readbuf[k] != 0xff) {
196                                         pr_err("error: verify 0xff "
197                                                "failed at %#llx\n",
198                                                (long long)addr);
199                                         errcnt += 1;
200                                         if (errcnt > 1000) {
201                                                 pr_err("error: too "
202                                                        "many errors\n");
203                                                 return -1;
204                                         }
205                                 }
206                 }
207                 if (vary_offset)
208                         do_vary_offset();
209         }
210         return err;
211 }
212
213 static int verify_eraseblock_in_one_go(int ebnum)
214 {
215         struct mtd_oob_ops ops;
216         int err = 0;
217         loff_t addr = ebnum * mtd->erasesize;
218         size_t len = mtd->ecclayout->oobavail * pgcnt;
219
220         prandom_bytes_state(&rnd_state, writebuf, len);
221         ops.mode      = MTD_OPS_AUTO_OOB;
222         ops.len       = 0;
223         ops.retlen    = 0;
224         ops.ooblen    = len;
225         ops.oobretlen = 0;
226         ops.ooboffs   = 0;
227         ops.datbuf    = NULL;
228         ops.oobbuf    = readbuf;
229         err = mtd_read_oob(mtd, addr, &ops);
230         if (err || ops.oobretlen != len) {
231                 pr_err("error: readoob failed at %#llx\n",
232                        (long long)addr);
233                 errcnt += 1;
234                 return err ? err : -1;
235         }
236         if (memcmp(readbuf, writebuf, len)) {
237                 pr_err("error: verify failed at %#llx\n",
238                        (long long)addr);
239                 errcnt += 1;
240                 if (errcnt > 1000) {
241                         pr_err("error: too many errors\n");
242                         return -1;
243                 }
244         }
245
246         return err;
247 }
248
249 static int verify_all_eraseblocks(void)
250 {
251         int err;
252         unsigned int i;
253
254         pr_info("verifying all eraseblocks\n");
255         for (i = 0; i < ebcnt; ++i) {
256                 if (bbt[i])
257                         continue;
258                 err = verify_eraseblock(i);
259                 if (err)
260                         return err;
261                 if (i % 256 == 0)
262                         pr_info("verified up to eraseblock %u\n", i);
263                 cond_resched();
264         }
265         pr_info("verified %u eraseblocks\n", i);
266         return 0;
267 }
268
269 static int __init mtd_oobtest_init(void)
270 {
271         int err = 0;
272         unsigned int i;
273         uint64_t tmp;
274         struct mtd_oob_ops ops;
275         loff_t addr = 0, addr0;
276
277         printk(KERN_INFO "\n");
278         printk(KERN_INFO "=================================================\n");
279
280         if (dev < 0) {
281                 pr_info("Please specify a valid mtd-device via module parameter\n");
282                 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
283                 return -EINVAL;
284         }
285
286         pr_info("MTD device: %d\n", dev);
287
288         mtd = get_mtd_device(NULL, dev);
289         if (IS_ERR(mtd)) {
290                 err = PTR_ERR(mtd);
291                 pr_err("error: cannot get MTD device\n");
292                 return err;
293         }
294
295         if (!mtd_type_is_nand(mtd)) {
296                 pr_info("this test requires NAND flash\n");
297                 goto out;
298         }
299
300         tmp = mtd->size;
301         do_div(tmp, mtd->erasesize);
302         ebcnt = tmp;
303         pgcnt = mtd->erasesize / mtd->writesize;
304
305         pr_info("MTD device size %llu, eraseblock size %u, "
306                "page size %u, count of eraseblocks %u, pages per "
307                "eraseblock %u, OOB size %u\n",
308                (unsigned long long)mtd->size, mtd->erasesize,
309                mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
310
311         err = -ENOMEM;
312         readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
313         if (!readbuf)
314                 goto out;
315         writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
316         if (!writebuf)
317                 goto out;
318         bbt = kzalloc(ebcnt, GFP_KERNEL);
319         if (!bbt)
320                 goto out;
321
322         err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
323         if (err)
324                 goto out;
325
326         use_offset = 0;
327         use_len = mtd->ecclayout->oobavail;
328         use_len_max = mtd->ecclayout->oobavail;
329         vary_offset = 0;
330
331         /* First test: write all OOB, read it back and verify */
332         pr_info("test 1 of 5\n");
333
334         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
335         if (err)
336                 goto out;
337
338         prandom_seed_state(&rnd_state, 1);
339         err = write_whole_device();
340         if (err)
341                 goto out;
342
343         prandom_seed_state(&rnd_state, 1);
344         err = verify_all_eraseblocks();
345         if (err)
346                 goto out;
347
348         /*
349          * Second test: write all OOB, a block at a time, read it back and
350          * verify.
351          */
352         pr_info("test 2 of 5\n");
353
354         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
355         if (err)
356                 goto out;
357
358         prandom_seed_state(&rnd_state, 3);
359         err = write_whole_device();
360         if (err)
361                 goto out;
362
363         /* Check all eraseblocks */
364         prandom_seed_state(&rnd_state, 3);
365         pr_info("verifying all eraseblocks\n");
366         for (i = 0; i < ebcnt; ++i) {
367                 if (bbt[i])
368                         continue;
369                 err = verify_eraseblock_in_one_go(i);
370                 if (err)
371                         goto out;
372                 if (i % 256 == 0)
373                         pr_info("verified up to eraseblock %u\n", i);
374                 cond_resched();
375         }
376         pr_info("verified %u eraseblocks\n", i);
377
378         /*
379          * Third test: write OOB at varying offsets and lengths, read it back
380          * and verify.
381          */
382         pr_info("test 3 of 5\n");
383
384         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
385         if (err)
386                 goto out;
387
388         /* Write all eraseblocks */
389         use_offset = 0;
390         use_len = mtd->ecclayout->oobavail;
391         use_len_max = mtd->ecclayout->oobavail;
392         vary_offset = 1;
393         prandom_seed_state(&rnd_state, 5);
394
395         err = write_whole_device();
396         if (err)
397                 goto out;
398
399         /* Check all eraseblocks */
400         use_offset = 0;
401         use_len = mtd->ecclayout->oobavail;
402         use_len_max = mtd->ecclayout->oobavail;
403         vary_offset = 1;
404         prandom_seed_state(&rnd_state, 5);
405         err = verify_all_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         /* Fourth test: try to write off end of device */
415         pr_info("test 4 of 5\n");
416
417         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
418         if (err)
419                 goto out;
420
421         addr0 = 0;
422         for (i = 0; i < ebcnt && bbt[i]; ++i)
423                 addr0 += mtd->erasesize;
424
425         /* Attempt to write off end of OOB */
426         ops.mode      = MTD_OPS_AUTO_OOB;
427         ops.len       = 0;
428         ops.retlen    = 0;
429         ops.ooblen    = 1;
430         ops.oobretlen = 0;
431         ops.ooboffs   = mtd->ecclayout->oobavail;
432         ops.datbuf    = NULL;
433         ops.oobbuf    = writebuf;
434         pr_info("attempting to start write past end of OOB\n");
435         pr_info("an error is expected...\n");
436         err = mtd_write_oob(mtd, addr0, &ops);
437         if (err) {
438                 pr_info("error occurred as expected\n");
439                 err = 0;
440         } else {
441                 pr_err("error: can write past end of OOB\n");
442                 errcnt += 1;
443         }
444
445         /* Attempt to read off end of OOB */
446         ops.mode      = MTD_OPS_AUTO_OOB;
447         ops.len       = 0;
448         ops.retlen    = 0;
449         ops.ooblen    = 1;
450         ops.oobretlen = 0;
451         ops.ooboffs   = mtd->ecclayout->oobavail;
452         ops.datbuf    = NULL;
453         ops.oobbuf    = readbuf;
454         pr_info("attempting to start read past end of OOB\n");
455         pr_info("an error is expected...\n");
456         err = mtd_read_oob(mtd, addr0, &ops);
457         if (err) {
458                 pr_info("error occurred as expected\n");
459                 err = 0;
460         } else {
461                 pr_err("error: can read past end of OOB\n");
462                 errcnt += 1;
463         }
464
465         if (bbt[ebcnt - 1])
466                 pr_info("skipping end of device tests because last "
467                        "block is bad\n");
468         else {
469                 /* Attempt to write off end of device */
470                 ops.mode      = MTD_OPS_AUTO_OOB;
471                 ops.len       = 0;
472                 ops.retlen    = 0;
473                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
474                 ops.oobretlen = 0;
475                 ops.ooboffs   = 0;
476                 ops.datbuf    = NULL;
477                 ops.oobbuf    = writebuf;
478                 pr_info("attempting to write past end of device\n");
479                 pr_info("an error is expected...\n");
480                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
481                 if (err) {
482                         pr_info("error occurred as expected\n");
483                         err = 0;
484                 } else {
485                         pr_err("error: wrote past end of device\n");
486                         errcnt += 1;
487                 }
488
489                 /* Attempt to read off end of device */
490                 ops.mode      = MTD_OPS_AUTO_OOB;
491                 ops.len       = 0;
492                 ops.retlen    = 0;
493                 ops.ooblen    = mtd->ecclayout->oobavail + 1;
494                 ops.oobretlen = 0;
495                 ops.ooboffs   = 0;
496                 ops.datbuf    = NULL;
497                 ops.oobbuf    = readbuf;
498                 pr_info("attempting to read past end of device\n");
499                 pr_info("an error is expected...\n");
500                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
501                 if (err) {
502                         pr_info("error occurred as expected\n");
503                         err = 0;
504                 } else {
505                         pr_err("error: read past end of device\n");
506                         errcnt += 1;
507                 }
508
509                 err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
510                 if (err)
511                         goto out;
512
513                 /* Attempt to write off end of device */
514                 ops.mode      = MTD_OPS_AUTO_OOB;
515                 ops.len       = 0;
516                 ops.retlen    = 0;
517                 ops.ooblen    = mtd->ecclayout->oobavail;
518                 ops.oobretlen = 0;
519                 ops.ooboffs   = 1;
520                 ops.datbuf    = NULL;
521                 ops.oobbuf    = writebuf;
522                 pr_info("attempting to write past end of device\n");
523                 pr_info("an error is expected...\n");
524                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
525                 if (err) {
526                         pr_info("error occurred as expected\n");
527                         err = 0;
528                 } else {
529                         pr_err("error: wrote past end of device\n");
530                         errcnt += 1;
531                 }
532
533                 /* Attempt to read off end of device */
534                 ops.mode      = MTD_OPS_AUTO_OOB;
535                 ops.len       = 0;
536                 ops.retlen    = 0;
537                 ops.ooblen    = mtd->ecclayout->oobavail;
538                 ops.oobretlen = 0;
539                 ops.ooboffs   = 1;
540                 ops.datbuf    = NULL;
541                 ops.oobbuf    = readbuf;
542                 pr_info("attempting to read past end of device\n");
543                 pr_info("an error is expected...\n");
544                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
545                 if (err) {
546                         pr_info("error occurred as expected\n");
547                         err = 0;
548                 } else {
549                         pr_err("error: read past end of device\n");
550                         errcnt += 1;
551                 }
552         }
553
554         /* Fifth test: write / read across block boundaries */
555         pr_info("test 5 of 5\n");
556
557         /* Erase all eraseblocks */
558         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
559         if (err)
560                 goto out;
561
562         /* Write all eraseblocks */
563         prandom_seed_state(&rnd_state, 11);
564         pr_info("writing OOBs of whole device\n");
565         for (i = 0; i < ebcnt - 1; ++i) {
566                 int cnt = 2;
567                 int pg;
568                 size_t sz = mtd->ecclayout->oobavail;
569                 if (bbt[i] || bbt[i + 1])
570                         continue;
571                 addr = (i + 1) * mtd->erasesize - mtd->writesize;
572                 prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
573                 for (pg = 0; pg < cnt; ++pg) {
574                         ops.mode      = MTD_OPS_AUTO_OOB;
575                         ops.len       = 0;
576                         ops.retlen    = 0;
577                         ops.ooblen    = sz;
578                         ops.oobretlen = 0;
579                         ops.ooboffs   = 0;
580                         ops.datbuf    = NULL;
581                         ops.oobbuf    = writebuf + pg * sz;
582                         err = mtd_write_oob(mtd, addr, &ops);
583                         if (err)
584                                 goto out;
585                         if (i % 256 == 0)
586                                 pr_info("written up to eraseblock %u\n", i);
587                         cond_resched();
588                         addr += mtd->writesize;
589                 }
590         }
591         pr_info("written %u eraseblocks\n", i);
592
593         /* Check all eraseblocks */
594         prandom_seed_state(&rnd_state, 11);
595         pr_info("verifying all eraseblocks\n");
596         for (i = 0; i < ebcnt - 1; ++i) {
597                 if (bbt[i] || bbt[i + 1])
598                         continue;
599                 prandom_bytes_state(&rnd_state, writebuf,
600                                         mtd->ecclayout->oobavail * 2);
601                 addr = (i + 1) * mtd->erasesize - mtd->writesize;
602                 ops.mode      = MTD_OPS_AUTO_OOB;
603                 ops.len       = 0;
604                 ops.retlen    = 0;
605                 ops.ooblen    = mtd->ecclayout->oobavail * 2;
606                 ops.oobretlen = 0;
607                 ops.ooboffs   = 0;
608                 ops.datbuf    = NULL;
609                 ops.oobbuf    = readbuf;
610                 err = mtd_read_oob(mtd, addr, &ops);
611                 if (err)
612                         goto out;
613                 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
614                         pr_err("error: verify failed at %#llx\n",
615                                (long long)addr);
616                         errcnt += 1;
617                         if (errcnt > 1000) {
618                                 pr_err("error: too many errors\n");
619                                 goto out;
620                         }
621                 }
622                 if (i % 256 == 0)
623                         pr_info("verified up to eraseblock %u\n", i);
624                 cond_resched();
625         }
626         pr_info("verified %u eraseblocks\n", i);
627
628         pr_info("finished with %d errors\n", errcnt);
629 out:
630         kfree(bbt);
631         kfree(writebuf);
632         kfree(readbuf);
633         put_mtd_device(mtd);
634         if (err)
635                 pr_info("error %d occurred\n", err);
636         printk(KERN_INFO "=================================================\n");
637         return err;
638 }
639 module_init(mtd_oobtest_init);
640
641 static void __exit mtd_oobtest_exit(void)
642 {
643         return;
644 }
645 module_exit(mtd_oobtest_exit);
646
647 MODULE_DESCRIPTION("Out-of-band test module");
648 MODULE_AUTHOR("Adrian Hunter");
649 MODULE_LICENSE("GPL");