2 * Copyright (C) 2006-2008 Nokia Corporation
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.
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
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.
17 * Test OOB read and write on MTD device.
19 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
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");
43 static struct mtd_info
*mtd
;
44 static unsigned char *readbuf
;
45 static unsigned char *writebuf
;
46 static unsigned char *bbt
;
51 static int use_offset
;
53 static int use_len_max
;
54 static int vary_offset
;
55 static struct rnd_state rnd_state
;
57 static void do_vary_offset(void)
62 if (use_offset
>= use_len_max
)
64 use_len
= use_len_max
- use_offset
;
68 static int write_eraseblock(int ebnum
)
71 struct mtd_oob_ops ops
;
73 loff_t addr
= ebnum
* mtd
->erasesize
;
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
;
82 ops
.ooboffs
= use_offset
;
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",
89 pr_err("error: use_len %d, use_offset %d\n",
92 return err
? err
: -1;
101 static int write_whole_device(void)
106 pr_info("writing OOBs of whole device\n");
107 for (i
= 0; i
< ebcnt
; ++i
) {
110 err
= write_eraseblock(i
);
114 pr_info("written up to eraseblock %u\n", i
);
117 pr_info("written %u eraseblocks\n", i
);
122 * Display the address, offset and data bytes at comparison failure.
123 * Return number of bitflips encountered.
125 static size_t memcmpshow(loff_t addr
, const void *cs
, const void *ct
, size_t count
)
127 const unsigned char *su1
, *su2
;
132 for (su1
= cs
, su2
= ct
; 0 < count
; ++su1
, ++su2
, count
--, i
++) {
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
);
144 static int verify_eraseblock(int ebnum
)
147 struct mtd_oob_ops ops
;
149 loff_t addr
= (loff_t
)ebnum
* mtd
->erasesize
;
152 prandom_bytes_state(&rnd_state
, writebuf
, use_len_max
* pgcnt
);
153 for (i
= 0; i
< pgcnt
; ++i
, addr
+= mtd
->writesize
) {
154 ops
.mode
= MTD_OPS_AUTO_OOB
;
157 ops
.ooblen
= use_len
;
159 ops
.ooboffs
= use_offset
;
161 ops
.oobbuf
= readbuf
;
162 err
= mtd_read_oob(mtd
, addr
, &ops
);
163 if (err
|| ops
.oobretlen
!= use_len
) {
164 pr_err("error: readoob failed at %#llx\n",
167 return err
? err
: -1;
170 bitflips
= memcmpshow(addr
, readbuf
,
171 writebuf
+ (use_len_max
* i
) + use_offset
,
173 if (bitflips
> bitflip_limit
) {
174 pr_err("error: verify failed at %#llx\n",
178 pr_err("error: too many errors\n");
181 } else if (bitflips
) {
182 pr_info("ignoring error as within bitflip_limit\n");
185 if (use_offset
!= 0 || use_len
< mtd
->ecclayout
->oobavail
) {
188 ops
.mode
= MTD_OPS_AUTO_OOB
;
191 ops
.ooblen
= mtd
->ecclayout
->oobavail
;
195 ops
.oobbuf
= readbuf
;
196 err
= mtd_read_oob(mtd
, addr
, &ops
);
197 if (err
|| ops
.oobretlen
!= mtd
->ecclayout
->oobavail
) {
198 pr_err("error: readoob failed at %#llx\n",
201 return err
? err
: -1;
203 bitflips
= memcmpshow(addr
, readbuf
+ use_offset
,
204 writebuf
+ (use_len_max
* i
) + use_offset
,
206 if (bitflips
> bitflip_limit
) {
207 pr_err("error: verify failed at %#llx\n",
211 pr_err("error: too many errors\n");
214 } else if (bitflips
) {
215 pr_info("ignoring error as within bitflip_limit\n");
218 for (k
= 0; k
< use_offset
; ++k
)
219 if (readbuf
[k
] != 0xff) {
220 pr_err("error: verify 0xff "
230 for (k
= use_offset
+ use_len
;
231 k
< mtd
->ecclayout
->oobavail
; ++k
)
232 if (readbuf
[k
] != 0xff) {
233 pr_err("error: verify 0xff "
250 static int verify_eraseblock_in_one_go(int ebnum
)
252 struct mtd_oob_ops ops
;
254 loff_t addr
= (loff_t
)ebnum
* mtd
->erasesize
;
255 size_t len
= mtd
->ecclayout
->oobavail
* pgcnt
;
256 size_t oobavail
= mtd
->ecclayout
->oobavail
;
260 prandom_bytes_state(&rnd_state
, writebuf
, len
);
261 ops
.mode
= MTD_OPS_AUTO_OOB
;
268 ops
.oobbuf
= readbuf
;
270 /* read entire block's OOB at one go */
271 err
= mtd_read_oob(mtd
, addr
, &ops
);
272 if (err
|| ops
.oobretlen
!= len
) {
273 pr_err("error: readoob failed at %#llx\n",
276 return err
? err
: -1;
279 /* verify one page OOB at a time for bitflip per page limit check */
280 for (i
= 0; i
< pgcnt
; ++i
, addr
+= mtd
->writesize
) {
281 bitflips
= memcmpshow(addr
, readbuf
+ (i
* oobavail
),
282 writebuf
+ (i
* oobavail
), oobavail
);
283 if (bitflips
> bitflip_limit
) {
284 pr_err("error: verify failed at %#llx\n",
288 pr_err("error: too many errors\n");
291 } else if (bitflips
) {
292 pr_info("ignoring error as within bitflip_limit\n");
299 static int verify_all_eraseblocks(void)
304 pr_info("verifying all eraseblocks\n");
305 for (i
= 0; i
< ebcnt
; ++i
) {
308 err
= verify_eraseblock(i
);
312 pr_info("verified up to eraseblock %u\n", i
);
315 pr_info("verified %u eraseblocks\n", i
);
319 static int __init
mtd_oobtest_init(void)
324 struct mtd_oob_ops ops
;
325 loff_t addr
= 0, addr0
;
327 printk(KERN_INFO
"\n");
328 printk(KERN_INFO
"=================================================\n");
331 pr_info("Please specify a valid mtd-device via module parameter\n");
332 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
336 pr_info("MTD device: %d\n", dev
);
338 mtd
= get_mtd_device(NULL
, dev
);
341 pr_err("error: cannot get MTD device\n");
345 if (!mtd_type_is_nand(mtd
)) {
346 pr_info("this test requires NAND flash\n");
351 do_div(tmp
, mtd
->erasesize
);
353 pgcnt
= mtd
->erasesize
/ mtd
->writesize
;
355 pr_info("MTD device size %llu, eraseblock size %u, "
356 "page size %u, count of eraseblocks %u, pages per "
357 "eraseblock %u, OOB size %u\n",
358 (unsigned long long)mtd
->size
, mtd
->erasesize
,
359 mtd
->writesize
, ebcnt
, pgcnt
, mtd
->oobsize
);
362 readbuf
= kmalloc(mtd
->erasesize
, GFP_KERNEL
);
365 writebuf
= kmalloc(mtd
->erasesize
, GFP_KERNEL
);
368 bbt
= kzalloc(ebcnt
, GFP_KERNEL
);
372 err
= mtdtest_scan_for_bad_eraseblocks(mtd
, bbt
, 0, ebcnt
);
377 use_len
= mtd
->ecclayout
->oobavail
;
378 use_len_max
= mtd
->ecclayout
->oobavail
;
381 /* First test: write all OOB, read it back and verify */
382 pr_info("test 1 of 5\n");
384 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
388 prandom_seed_state(&rnd_state
, 1);
389 err
= write_whole_device();
393 prandom_seed_state(&rnd_state
, 1);
394 err
= verify_all_eraseblocks();
399 * Second test: write all OOB, a block at a time, read it back and
402 pr_info("test 2 of 5\n");
404 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
408 prandom_seed_state(&rnd_state
, 3);
409 err
= write_whole_device();
413 /* Check all eraseblocks */
414 prandom_seed_state(&rnd_state
, 3);
415 pr_info("verifying all eraseblocks\n");
416 for (i
= 0; i
< ebcnt
; ++i
) {
419 err
= verify_eraseblock_in_one_go(i
);
423 pr_info("verified up to eraseblock %u\n", i
);
426 pr_info("verified %u eraseblocks\n", i
);
429 * Third test: write OOB at varying offsets and lengths, read it back
432 pr_info("test 3 of 5\n");
434 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
438 /* Write all eraseblocks */
440 use_len
= mtd
->ecclayout
->oobavail
;
441 use_len_max
= mtd
->ecclayout
->oobavail
;
443 prandom_seed_state(&rnd_state
, 5);
445 err
= write_whole_device();
449 /* Check all eraseblocks */
451 use_len
= mtd
->ecclayout
->oobavail
;
452 use_len_max
= mtd
->ecclayout
->oobavail
;
454 prandom_seed_state(&rnd_state
, 5);
455 err
= verify_all_eraseblocks();
460 use_len
= mtd
->ecclayout
->oobavail
;
461 use_len_max
= mtd
->ecclayout
->oobavail
;
464 /* Fourth test: try to write off end of device */
465 pr_info("test 4 of 5\n");
467 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
472 for (i
= 0; i
< ebcnt
&& bbt
[i
]; ++i
)
473 addr0
+= mtd
->erasesize
;
475 /* Attempt to write off end of OOB */
476 ops
.mode
= MTD_OPS_AUTO_OOB
;
481 ops
.ooboffs
= mtd
->ecclayout
->oobavail
;
483 ops
.oobbuf
= writebuf
;
484 pr_info("attempting to start write past end of OOB\n");
485 pr_info("an error is expected...\n");
486 err
= mtd_write_oob(mtd
, addr0
, &ops
);
488 pr_info("error occurred as expected\n");
491 pr_err("error: can write past end of OOB\n");
495 /* Attempt to read off end of OOB */
496 ops
.mode
= MTD_OPS_AUTO_OOB
;
501 ops
.ooboffs
= mtd
->ecclayout
->oobavail
;
503 ops
.oobbuf
= readbuf
;
504 pr_info("attempting to start read past end of OOB\n");
505 pr_info("an error is expected...\n");
506 err
= mtd_read_oob(mtd
, addr0
, &ops
);
508 pr_info("error occurred as expected\n");
511 pr_err("error: can read past end of OOB\n");
516 pr_info("skipping end of device tests because last "
519 /* Attempt to write off end of device */
520 ops
.mode
= MTD_OPS_AUTO_OOB
;
523 ops
.ooblen
= mtd
->ecclayout
->oobavail
+ 1;
527 ops
.oobbuf
= writebuf
;
528 pr_info("attempting to write past end of device\n");
529 pr_info("an error is expected...\n");
530 err
= mtd_write_oob(mtd
, mtd
->size
- mtd
->writesize
, &ops
);
532 pr_info("error occurred as expected\n");
535 pr_err("error: wrote past end of device\n");
539 /* Attempt to read off end of device */
540 ops
.mode
= MTD_OPS_AUTO_OOB
;
543 ops
.ooblen
= mtd
->ecclayout
->oobavail
+ 1;
547 ops
.oobbuf
= readbuf
;
548 pr_info("attempting to read past end of device\n");
549 pr_info("an error is expected...\n");
550 err
= mtd_read_oob(mtd
, mtd
->size
- mtd
->writesize
, &ops
);
552 pr_info("error occurred as expected\n");
555 pr_err("error: read past end of device\n");
559 err
= mtdtest_erase_eraseblock(mtd
, ebcnt
- 1);
563 /* Attempt to write off end of device */
564 ops
.mode
= MTD_OPS_AUTO_OOB
;
567 ops
.ooblen
= mtd
->ecclayout
->oobavail
;
571 ops
.oobbuf
= writebuf
;
572 pr_info("attempting to write past end of device\n");
573 pr_info("an error is expected...\n");
574 err
= mtd_write_oob(mtd
, mtd
->size
- mtd
->writesize
, &ops
);
576 pr_info("error occurred as expected\n");
579 pr_err("error: wrote past end of device\n");
583 /* Attempt to read off end of device */
584 ops
.mode
= MTD_OPS_AUTO_OOB
;
587 ops
.ooblen
= mtd
->ecclayout
->oobavail
;
591 ops
.oobbuf
= readbuf
;
592 pr_info("attempting to read past end of device\n");
593 pr_info("an error is expected...\n");
594 err
= mtd_read_oob(mtd
, mtd
->size
- mtd
->writesize
, &ops
);
596 pr_info("error occurred as expected\n");
599 pr_err("error: read past end of device\n");
604 /* Fifth test: write / read across block boundaries */
605 pr_info("test 5 of 5\n");
607 /* Erase all eraseblocks */
608 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
612 /* Write all eraseblocks */
613 prandom_seed_state(&rnd_state
, 11);
614 pr_info("writing OOBs of whole device\n");
615 for (i
= 0; i
< ebcnt
- 1; ++i
) {
618 size_t sz
= mtd
->ecclayout
->oobavail
;
619 if (bbt
[i
] || bbt
[i
+ 1])
621 addr
= (loff_t
)(i
+ 1) * mtd
->erasesize
- mtd
->writesize
;
622 prandom_bytes_state(&rnd_state
, writebuf
, sz
* cnt
);
623 for (pg
= 0; pg
< cnt
; ++pg
) {
624 ops
.mode
= MTD_OPS_AUTO_OOB
;
631 ops
.oobbuf
= writebuf
+ pg
* sz
;
632 err
= mtd_write_oob(mtd
, addr
, &ops
);
636 pr_info("written up to eraseblock %u\n", i
);
638 addr
+= mtd
->writesize
;
641 pr_info("written %u eraseblocks\n", i
);
643 /* Check all eraseblocks */
644 prandom_seed_state(&rnd_state
, 11);
645 pr_info("verifying all eraseblocks\n");
646 for (i
= 0; i
< ebcnt
- 1; ++i
) {
647 if (bbt
[i
] || bbt
[i
+ 1])
649 prandom_bytes_state(&rnd_state
, writebuf
,
650 mtd
->ecclayout
->oobavail
* 2);
651 addr
= (loff_t
)(i
+ 1) * mtd
->erasesize
- mtd
->writesize
;
652 ops
.mode
= MTD_OPS_AUTO_OOB
;
655 ops
.ooblen
= mtd
->ecclayout
->oobavail
* 2;
659 ops
.oobbuf
= readbuf
;
660 err
= mtd_read_oob(mtd
, addr
, &ops
);
663 if (memcmpshow(addr
, readbuf
, writebuf
,
664 mtd
->ecclayout
->oobavail
* 2)) {
665 pr_err("error: verify failed at %#llx\n",
669 pr_err("error: too many errors\n");
674 pr_info("verified up to eraseblock %u\n", i
);
677 pr_info("verified %u eraseblocks\n", i
);
679 pr_info("finished with %d errors\n", errcnt
);
686 pr_info("error %d occurred\n", err
);
687 printk(KERN_INFO
"=================================================\n");
690 module_init(mtd_oobtest_init
);
692 static void __exit
mtd_oobtest_exit(void)
696 module_exit(mtd_oobtest_exit
);
698 MODULE_DESCRIPTION("Out-of-band test module");
699 MODULE_AUTHOR("Adrian Hunter");
700 MODULE_LICENSE("GPL");