Bluetooth: hci_uart: Use generic functionality from Broadcom module
[linux/fpc-iii.git] / drivers / mtd / tests / oobtest.c
blob5e061186eab181c927d41568dd73b7cd9e486b25
1 /*
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
11 * more details.
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>
34 #include "mtd_test.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;
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;
57 static void do_vary_offset(void)
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;
68 static int write_eraseblock(int ebnum)
70 int i;
71 struct mtd_oob_ops ops;
72 int err = 0;
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;
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;
94 if (vary_offset)
95 do_vary_offset();
98 return err;
101 static int write_whole_device(void)
103 int err;
104 unsigned int i;
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();
117 pr_info("written %u eraseblocks\n", i);
118 return 0;
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;
128 int res;
129 size_t i = 0;
130 size_t bitflips = 0;
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);
141 return bitflips;
144 static int verify_eraseblock(int ebnum)
146 int i;
147 struct mtd_oob_ops ops;
148 int err = 0;
149 loff_t addr = (loff_t)ebnum * mtd->erasesize;
150 size_t bitflips;
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;
155 ops.len = 0;
156 ops.retlen = 0;
157 ops.ooblen = use_len;
158 ops.oobretlen = 0;
159 ops.ooboffs = use_offset;
160 ops.datbuf = NULL;
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",
165 (long long)addr);
166 errcnt += 1;
167 return err ? err : -1;
170 bitflips = memcmpshow(addr, readbuf,
171 writebuf + (use_len_max * i) + use_offset,
172 use_len);
173 if (bitflips > bitflip_limit) {
174 pr_err("error: verify failed at %#llx\n",
175 (long long)addr);
176 errcnt += 1;
177 if (errcnt > 1000) {
178 pr_err("error: too many errors\n");
179 return -1;
181 } else if (bitflips) {
182 pr_info("ignoring error as within bitflip_limit\n");
185 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
186 int k;
188 ops.mode = MTD_OPS_AUTO_OOB;
189 ops.len = 0;
190 ops.retlen = 0;
191 ops.ooblen = mtd->ecclayout->oobavail;
192 ops.oobretlen = 0;
193 ops.ooboffs = 0;
194 ops.datbuf = NULL;
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",
199 (long long)addr);
200 errcnt += 1;
201 return err ? err : -1;
203 bitflips = memcmpshow(addr, readbuf + use_offset,
204 writebuf + (use_len_max * i) + use_offset,
205 use_len);
206 if (bitflips > bitflip_limit) {
207 pr_err("error: verify failed at %#llx\n",
208 (long long)addr);
209 errcnt += 1;
210 if (errcnt > 1000) {
211 pr_err("error: too many errors\n");
212 return -1;
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 "
221 "failed at %#llx\n",
222 (long long)addr);
223 errcnt += 1;
224 if (errcnt > 1000) {
225 pr_err("error: too "
226 "many errors\n");
227 return -1;
230 for (k = use_offset + use_len;
231 k < mtd->ecclayout->oobavail; ++k)
232 if (readbuf[k] != 0xff) {
233 pr_err("error: verify 0xff "
234 "failed at %#llx\n",
235 (long long)addr);
236 errcnt += 1;
237 if (errcnt > 1000) {
238 pr_err("error: too "
239 "many errors\n");
240 return -1;
244 if (vary_offset)
245 do_vary_offset();
247 return err;
250 static int verify_eraseblock_in_one_go(int ebnum)
252 struct mtd_oob_ops ops;
253 int err = 0;
254 loff_t addr = (loff_t)ebnum * mtd->erasesize;
255 size_t len = mtd->ecclayout->oobavail * pgcnt;
256 size_t oobavail = mtd->ecclayout->oobavail;
257 size_t bitflips;
258 int i;
260 prandom_bytes_state(&rnd_state, writebuf, len);
261 ops.mode = MTD_OPS_AUTO_OOB;
262 ops.len = 0;
263 ops.retlen = 0;
264 ops.ooblen = len;
265 ops.oobretlen = 0;
266 ops.ooboffs = 0;
267 ops.datbuf = NULL;
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",
274 (long long)addr);
275 errcnt += 1;
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",
285 (long long)addr);
286 errcnt += 1;
287 if (errcnt > 1000) {
288 pr_err("error: too many errors\n");
289 return -1;
291 } else if (bitflips) {
292 pr_info("ignoring error as within bitflip_limit\n");
296 return err;
299 static int verify_all_eraseblocks(void)
301 int err;
302 unsigned int i;
304 pr_info("verifying all eraseblocks\n");
305 for (i = 0; i < ebcnt; ++i) {
306 if (bbt[i])
307 continue;
308 err = verify_eraseblock(i);
309 if (err)
310 return err;
311 if (i % 256 == 0)
312 pr_info("verified up to eraseblock %u\n", i);
313 cond_resched();
315 pr_info("verified %u eraseblocks\n", i);
316 return 0;
319 static int __init mtd_oobtest_init(void)
321 int err = 0;
322 unsigned int i;
323 uint64_t tmp;
324 struct mtd_oob_ops ops;
325 loff_t addr = 0, addr0;
327 printk(KERN_INFO "\n");
328 printk(KERN_INFO "=================================================\n");
330 if (dev < 0) {
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");
333 return -EINVAL;
336 pr_info("MTD device: %d\n", dev);
338 mtd = get_mtd_device(NULL, dev);
339 if (IS_ERR(mtd)) {
340 err = PTR_ERR(mtd);
341 pr_err("error: cannot get MTD device\n");
342 return err;
345 if (!mtd_type_is_nand(mtd)) {
346 pr_info("this test requires NAND flash\n");
347 goto out;
350 tmp = mtd->size;
351 do_div(tmp, mtd->erasesize);
352 ebcnt = tmp;
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);
361 err = -ENOMEM;
362 readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
363 if (!readbuf)
364 goto out;
365 writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
366 if (!writebuf)
367 goto out;
368 bbt = kzalloc(ebcnt, GFP_KERNEL);
369 if (!bbt)
370 goto out;
372 err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
373 if (err)
374 goto out;
376 use_offset = 0;
377 use_len = mtd->ecclayout->oobavail;
378 use_len_max = mtd->ecclayout->oobavail;
379 vary_offset = 0;
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);
385 if (err)
386 goto out;
388 prandom_seed_state(&rnd_state, 1);
389 err = write_whole_device();
390 if (err)
391 goto out;
393 prandom_seed_state(&rnd_state, 1);
394 err = verify_all_eraseblocks();
395 if (err)
396 goto out;
399 * Second test: write all OOB, a block at a time, read it back and
400 * verify.
402 pr_info("test 2 of 5\n");
404 err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
405 if (err)
406 goto out;
408 prandom_seed_state(&rnd_state, 3);
409 err = write_whole_device();
410 if (err)
411 goto out;
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) {
417 if (bbt[i])
418 continue;
419 err = verify_eraseblock_in_one_go(i);
420 if (err)
421 goto out;
422 if (i % 256 == 0)
423 pr_info("verified up to eraseblock %u\n", i);
424 cond_resched();
426 pr_info("verified %u eraseblocks\n", i);
429 * Third test: write OOB at varying offsets and lengths, read it back
430 * and verify.
432 pr_info("test 3 of 5\n");
434 err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
435 if (err)
436 goto out;
438 /* Write all eraseblocks */
439 use_offset = 0;
440 use_len = mtd->ecclayout->oobavail;
441 use_len_max = mtd->ecclayout->oobavail;
442 vary_offset = 1;
443 prandom_seed_state(&rnd_state, 5);
445 err = write_whole_device();
446 if (err)
447 goto out;
449 /* Check all eraseblocks */
450 use_offset = 0;
451 use_len = mtd->ecclayout->oobavail;
452 use_len_max = mtd->ecclayout->oobavail;
453 vary_offset = 1;
454 prandom_seed_state(&rnd_state, 5);
455 err = verify_all_eraseblocks();
456 if (err)
457 goto out;
459 use_offset = 0;
460 use_len = mtd->ecclayout->oobavail;
461 use_len_max = mtd->ecclayout->oobavail;
462 vary_offset = 0;
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);
468 if (err)
469 goto out;
471 addr0 = 0;
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;
477 ops.len = 0;
478 ops.retlen = 0;
479 ops.ooblen = 1;
480 ops.oobretlen = 0;
481 ops.ooboffs = mtd->ecclayout->oobavail;
482 ops.datbuf = NULL;
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);
487 if (err) {
488 pr_info("error occurred as expected\n");
489 err = 0;
490 } else {
491 pr_err("error: can write past end of OOB\n");
492 errcnt += 1;
495 /* Attempt to read off end of OOB */
496 ops.mode = MTD_OPS_AUTO_OOB;
497 ops.len = 0;
498 ops.retlen = 0;
499 ops.ooblen = 1;
500 ops.oobretlen = 0;
501 ops.ooboffs = mtd->ecclayout->oobavail;
502 ops.datbuf = NULL;
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);
507 if (err) {
508 pr_info("error occurred as expected\n");
509 err = 0;
510 } else {
511 pr_err("error: can read past end of OOB\n");
512 errcnt += 1;
515 if (bbt[ebcnt - 1])
516 pr_info("skipping end of device tests because last "
517 "block is bad\n");
518 else {
519 /* Attempt to write off end of device */
520 ops.mode = MTD_OPS_AUTO_OOB;
521 ops.len = 0;
522 ops.retlen = 0;
523 ops.ooblen = mtd->ecclayout->oobavail + 1;
524 ops.oobretlen = 0;
525 ops.ooboffs = 0;
526 ops.datbuf = NULL;
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);
531 if (err) {
532 pr_info("error occurred as expected\n");
533 err = 0;
534 } else {
535 pr_err("error: wrote past end of device\n");
536 errcnt += 1;
539 /* Attempt to read off end of device */
540 ops.mode = MTD_OPS_AUTO_OOB;
541 ops.len = 0;
542 ops.retlen = 0;
543 ops.ooblen = mtd->ecclayout->oobavail + 1;
544 ops.oobretlen = 0;
545 ops.ooboffs = 0;
546 ops.datbuf = NULL;
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);
551 if (err) {
552 pr_info("error occurred as expected\n");
553 err = 0;
554 } else {
555 pr_err("error: read past end of device\n");
556 errcnt += 1;
559 err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
560 if (err)
561 goto out;
563 /* Attempt to write off end of device */
564 ops.mode = MTD_OPS_AUTO_OOB;
565 ops.len = 0;
566 ops.retlen = 0;
567 ops.ooblen = mtd->ecclayout->oobavail;
568 ops.oobretlen = 0;
569 ops.ooboffs = 1;
570 ops.datbuf = NULL;
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);
575 if (err) {
576 pr_info("error occurred as expected\n");
577 err = 0;
578 } else {
579 pr_err("error: wrote past end of device\n");
580 errcnt += 1;
583 /* Attempt to read off end of device */
584 ops.mode = MTD_OPS_AUTO_OOB;
585 ops.len = 0;
586 ops.retlen = 0;
587 ops.ooblen = mtd->ecclayout->oobavail;
588 ops.oobretlen = 0;
589 ops.ooboffs = 1;
590 ops.datbuf = NULL;
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);
595 if (err) {
596 pr_info("error occurred as expected\n");
597 err = 0;
598 } else {
599 pr_err("error: read past end of device\n");
600 errcnt += 1;
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);
609 if (err)
610 goto out;
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) {
616 int cnt = 2;
617 int pg;
618 size_t sz = mtd->ecclayout->oobavail;
619 if (bbt[i] || bbt[i + 1])
620 continue;
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;
625 ops.len = 0;
626 ops.retlen = 0;
627 ops.ooblen = sz;
628 ops.oobretlen = 0;
629 ops.ooboffs = 0;
630 ops.datbuf = NULL;
631 ops.oobbuf = writebuf + pg * sz;
632 err = mtd_write_oob(mtd, addr, &ops);
633 if (err)
634 goto out;
635 if (i % 256 == 0)
636 pr_info("written up to eraseblock %u\n", i);
637 cond_resched();
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])
648 continue;
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;
653 ops.len = 0;
654 ops.retlen = 0;
655 ops.ooblen = mtd->ecclayout->oobavail * 2;
656 ops.oobretlen = 0;
657 ops.ooboffs = 0;
658 ops.datbuf = NULL;
659 ops.oobbuf = readbuf;
660 err = mtd_read_oob(mtd, addr, &ops);
661 if (err)
662 goto out;
663 if (memcmpshow(addr, readbuf, writebuf,
664 mtd->ecclayout->oobavail * 2)) {
665 pr_err("error: verify failed at %#llx\n",
666 (long long)addr);
667 errcnt += 1;
668 if (errcnt > 1000) {
669 pr_err("error: too many errors\n");
670 goto out;
673 if (i % 256 == 0)
674 pr_info("verified up to eraseblock %u\n", i);
675 cond_resched();
677 pr_info("verified %u eraseblocks\n", i);
679 pr_info("finished with %d errors\n", errcnt);
680 out:
681 kfree(bbt);
682 kfree(writebuf);
683 kfree(readbuf);
684 put_mtd_device(mtd);
685 if (err)
686 pr_info("error %d occurred\n", err);
687 printk(KERN_INFO "=================================================\n");
688 return err;
690 module_init(mtd_oobtest_init);
692 static void __exit mtd_oobtest_exit(void)
694 return;
696 module_exit(mtd_oobtest_exit);
698 MODULE_DESCRIPTION("Out-of-band test module");
699 MODULE_AUTHOR("Adrian Hunter");
700 MODULE_LICENSE("GPL");