1 #include <linux/init.h>
\r
2 #include <linux/slab.h>
\r
3 #include <linux/fs.h>
\r
4 #include <asm/uaccess.h>
\r
5 #include <linux/types.h>
\r
6 #include <linux/moduleparam.h>
\r
7 #include <linux/kernel.h>
\r
8 #include <linux/module.h>
\r
9 #include <linux/mtd/mtd.h>
\r
10 #include <linux/delay.h>
\r
11 #include <asm/div64.h>
\r
12 #include <linux/err.h>
\r
13 #include <linux/sched.h>
\r
14 #include <linux/random.h>
\r
15 #include <linux/vmalloc.h>
\r
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
\r
21 module_param(dev, int, S_IRUGO);
\r
22 MODULE_PARM_DESC(dev, "MTD device number to use");
\r
24 static struct mtd_info *mtd = NULL;
\r
25 static unsigned char *bbt = NULL;
\r
31 static int subpgsize;
\r
32 static int use_offset;
\r
34 static int use_len_max;
\r
35 static int vary_offset;
\r
36 static struct rnd_state rnd_state;
\r
37 static struct timeval start, finish;
\r
38 static int goodebcnt;
\r
40 static int subcount;
\r
42 static unsigned char * writebuf;
\r
43 static unsigned char *readbuf;
\r
44 static int *offsets;
\r
45 static unsigned char *twopages;
\r
46 static unsigned char *boundary;
\r
48 static inline void mtd_test_start_timing(void)
\r
50 do_gettimeofday(&start);
\r
53 static inline void mtd_test_stop_timing(void)
\r
55 do_gettimeofday(&finish);
\r
58 void mtd_test_dump_buf(unsigned char *buf, unsigned int num, unsigned int col_num)
\r
60 unsigned int i = 0, j = 0;
\r
65 for(i = 0; i < num; i ++)
\r
67 if((i%col_num) == 0) {
\r
70 pr_info("%.8x:", j);
\r
75 pr_info("%.2x", buf[i]);
\r
80 static int mtd_test_erase_eraseblock(int ebnum, int blocks)
\r
83 struct erase_info ei = {0};
\r
89 ei.addr = ebnum * mtd->erasesize;
\r
90 ei.len = mtd->erasesize * blocks;
\r
92 err = mtd_erase(mtd, &ei);
\r
94 pr_err("error %d while erasing EB %d\n", err, ebnum);
\r
98 if (ei.state == MTD_ERASE_FAILED) {
\r
99 pr_err("Some erase error occurred at EB %d\n", ebnum);
\r
106 static int mtd_test_erase_whole_device(void)
\r
109 unsigned int i = 0;
\r
111 for (i = 0; i < ebcnt; ++i) {
\r
114 err = mtd_test_erase_eraseblock(i, 0);
\r
122 static int mtd_test_scan_bad_block(void)
\r
124 unsigned int i = 0, bad = 0;
\r
126 bbt = (unsigned char *)vmalloc(ebcnt);
\r
128 pr_info("error: cannot allocate memory\n");
\r
132 pr_info("scanning for bad eraseblocks first\n");
\r
133 for (i = 0; i < ebcnt; ++i) {
\r
134 bbt[i] = mtd_block_isbad(mtd, i * mtd->erasesize) ? 1 : 0;
\r
139 pr_info("scanned %d eraseblocks, %d are bad\n", ebcnt, bad);
\r
140 goodebcnt = ebcnt - bad;
\r
144 static int readtest_read_page(int ebnum, unsigned char *databuf, unsigned char *oobbuf)
\r
146 int i = 0, ret = 0;
\r
147 unsigned int read = 0;
\r
148 struct mtd_oob_ops ops = {0};
\r
149 loff_t addr = ebnum * mtd->erasesize;
\r
151 memset(databuf, 0 , mtd->erasesize);
\r
152 memset(oobbuf, 0 , mtd->erasesize);
\r
153 for (i = 0; i < pgcnt; i++) {
\r
154 ret = mtd_read(mtd, addr, pgsize, &read, databuf);
\r
155 if (ret || read != pgsize) {
\r
156 pr_err("error: read failed at %#llx, ret: %d read: %d\n",
\r
157 (long long)addr, ret, read);
\r
158 return ret ? ret : -EINVAL;
\r
161 ops.mode = MTD_OPS_PLACE_OOB;
\r
164 ops.ooblen = mtd->oobsize;
\r
168 ops.oobbuf = oobbuf;
\r
169 ret = mtd_read_oob(mtd, addr, &ops);
\r
170 if (ret || ops.oobretlen != mtd->oobsize) {
\r
171 pr_err("error: read oob failed at "
\r
172 "%#llx, ret: %d oobretlen: %d\n", (long long)addr, ret, ops.oobretlen);
\r
173 return ret ? ret : -EINVAL;
\r
175 databuf += mtd->writesize;
\r
176 oobbuf += mtd->oobsize;
\r
177 addr += mtd->writesize;
\r
183 static int mtd_test_readtest(void)
\r
186 unsigned int i = 0;
\r
187 unsigned char *iobuf = NULL, *iobuf1 = NULL;
\r
189 iobuf = (unsigned char *)kmalloc(mtd->erasesize, GFP_KERNEL);
\r
190 iobuf1 = (unsigned char *)kmalloc(mtd->erasesize, GFP_KERNEL);
\r
191 if (!iobuf1 || !iobuf) {
\r
192 pr_err("error: cannot allocate enough memory, %d, 0x%.8x, 0x%.8x!\n", mtd->erasesize, (unsigned int)iobuf, (unsigned int)iobuf1);
\r
196 pr_info("readtest begin!\n");
\r
197 for (i = 0; i < ebcnt; ++i) {
\r
201 ret = readtest_read_page(i, iobuf, iobuf1);
\r
203 pr_err("read block %d failed!\n", i);
\r
204 mtd_test_dump_buf(iobuf, mtd->erasesize, 32);
\r
205 mtd_test_dump_buf(iobuf1, mtd->oobsize, 32);
\r
211 pr_info("readtest finished successfully!\n");
\r
218 static int pagetest_write_eraseblock(int ebnum)
\r
221 size_t written = 0;
\r
222 loff_t addr = ebnum * mtd->erasesize;
\r
224 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
\r
226 err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
\r
227 if (err || written != mtd->erasesize) {
\r
228 pr_err("%s, write failed at %#llx\n", __func__, (long long)addr);
\r
229 return err ? err : -EINVAL;
\r
235 static int pagetest_verify_eraseblock(int ebnum)
\r
239 uint32_t j = 0, i = 0;
\r
240 loff_t addr0 = 0, addrn = 0;
\r
241 loff_t addr = ebnum * mtd->erasesize;
\r
243 for (i = 0; i < ebcnt && bbt[i]; ++i)
\r
244 addr0 += mtd->erasesize;
\r
247 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
\r
248 addrn -= mtd->erasesize;
\r
250 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
\r
251 for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
\r
252 /* Do a read to set the internal dataRAMs to different data */
\r
253 err = mtd_read(mtd, addr0, bufsize, &read, twopages);
\r
254 if (mtd_is_bitflip(err))
\r
256 if (err || read != bufsize) {
\r
257 pr_err("2.1 error: read failed at %#llx\n",
\r
261 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
\r
262 if (mtd_is_bitflip(err))
\r
264 if (err || read != bufsize) {
\r
265 pr_err("2.2 error: read failed at %#llx\n",
\r
266 (long long)(addrn - bufsize));
\r
269 memset(twopages, 0, bufsize);
\r
270 err = mtd_read(mtd, addr, bufsize, &read, twopages);
\r
271 if (mtd_is_bitflip(err))
\r
273 if (err || read != bufsize) {
\r
274 pr_err("2.3 error: read failed at %#llx\n",
\r
278 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
\r
279 pr_err("2.4 error: verify failed at %#llx\n",
\r
283 /* Check boundary between eraseblocks */
\r
284 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
\r
285 struct rnd_state old_state = rnd_state;
\r
287 /* Do a read to set the internal dataRAMs to different data */
\r
288 err = mtd_read(mtd, addr0, bufsize, &read, twopages);
\r
289 if (mtd_is_bitflip(err))
\r
291 if (err || read != bufsize) {
\r
292 pr_err("2.5 error: read failed at %#llx\n",
\r
296 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
\r
297 if (mtd_is_bitflip(err))
\r
299 if (err || read != bufsize) {
\r
300 pr_err("2.6 error: read failed at %#llx\n",
\r
301 (long long)(addrn - bufsize));
\r
304 memset(twopages, 0, bufsize);
\r
305 err = mtd_read(mtd, addr, bufsize, &read, twopages);
\r
306 if (mtd_is_bitflip(err))
\r
308 if (err || read != bufsize) {
\r
309 pr_err("2.7 error: read failed at %#llx\n",
\r
313 memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
\r
314 prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
\r
315 if (memcmp(twopages, boundary, bufsize)) {
\r
316 pr_err("2.8 error: verify failed at %#llx\n",
\r
319 rnd_state = old_state;
\r
324 static int pagetest_crosstest(void)
\r
328 unsigned int i = 0;
\r
329 loff_t addr = 0, addr0 = 0, addrn = 0;
\r
330 unsigned char *pp1 = NULL, *pp2 = NULL, *pp3 = NULL, *pp4 = NULL;
\r
332 // pr_info("crosstest\n");
\r
333 pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
\r
335 pr_err("2.9 error: cannot allocate memory\n");
\r
338 pp2 = pp1 + pgsize;
\r
339 pp3 = pp2 + pgsize;
\r
340 pp4 = pp3 + pgsize;
\r
341 memset(pp1, 0, pgsize * 4);
\r
344 for (i = 0; i < ebcnt && bbt[i]; ++i)
\r
345 addr0 += mtd->erasesize;
\r
348 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
\r
349 addrn -= mtd->erasesize;
\r
351 /* Read 2nd-to-last page to pp1 */
\r
352 addr = addrn - pgsize - pgsize;
\r
353 err = mtd_read(mtd, addr, pgsize, &read, pp1);
\r
354 if (mtd_is_bitflip(err))
\r
356 if (err || read != pgsize) {
\r
357 pr_err("2.10 error: read failed at %#llx\n",
\r
363 /* Read 3rd-to-last page to pp1 */
\r
364 addr = addrn - pgsize - pgsize - pgsize;
\r
365 err = mtd_read(mtd, addr, pgsize, &read, pp1);
\r
366 if (mtd_is_bitflip(err))
\r
368 if (err || read != pgsize) {
\r
369 pr_err("2.11 error: read failed at %#llx\n",
\r
375 /* Read first page to pp2 */
\r
377 // pr_info("reading page at %#llx\n", (long long)addr);
\r
378 err = mtd_read(mtd, addr, pgsize, &read, pp2);
\r
379 if (mtd_is_bitflip(err))
\r
381 if (err || read != pgsize) {
\r
382 pr_err("2.12 error: read failed at %#llx\n",
\r
388 /* Read last page to pp3 */
\r
389 addr = addrn - pgsize;
\r
390 // pr_info("reading page at %#llx\n", (long long)addr);
\r
391 err = mtd_read(mtd, addr, pgsize, &read, pp3);
\r
392 if (mtd_is_bitflip(err))
\r
394 if (err || read != pgsize) {
\r
395 pr_err("2.13 error: read failed at %#llx\n",
\r
401 /* Read first page again to pp4 */
\r
403 // pr_info("reading page at %#llx\n", (long long)addr);
\r
404 err = mtd_read(mtd, addr, pgsize, &read, pp4);
\r
405 if (mtd_is_bitflip(err))
\r
407 if (err || read != pgsize) {
\r
408 pr_err("2.14 error: read failed at %#llx\n",
\r
414 /* pp2 and pp4 should be the same */
\r
415 // pr_info("verifying pages read at %#llx match\n", (long long)addr0);
\r
416 if (memcmp(pp2, pp4, pgsize)) {
\r
417 pr_err("2.15 verify failed!\n");
\r
419 // pr_info("crosstest ok\n");
\r
424 static int pagetest_erasecrosstest(void)
\r
428 char *readbuf = twopages;
\r
429 size_t read = 0, written = 0;
\r
430 unsigned int i = 0, ebnum = 0, ebnum2 = 0;
\r
432 // pr_info("erasecrosstest\n");
\r
436 for (i = 0; i < ebcnt && bbt[i]; ++i) {
\r
437 addr0 += mtd->erasesize;
\r
441 ebnum2 = ebcnt - 1;
\r
442 while (ebnum2 && bbt[ebnum2])
\r
445 // pr_info("erasing block %d\n", ebnum);
\r
446 err = mtd_test_erase_eraseblock(ebnum, 0);
\r
450 // pr_info("writing 1st page of block %d\n", ebnum);
\r
451 prandom_bytes_state(&rnd_state, writebuf, pgsize);
\r
452 strcpy(writebuf, "There is no data like this!");
\r
453 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
\r
454 if (err || written != pgsize) {
\r
455 pr_err("2.16 error: write failed at %#llx\n",
\r
457 return err ? err : -EINVAL;
\r
460 // pr_info("reading 1st page of block %d\n", ebnum);
\r
461 memset(readbuf, 0, pgsize);
\r
462 err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
\r
463 if (mtd_is_bitflip(err))
\r
465 if (err || read != pgsize) {
\r
466 pr_err("2.17 error: read failed at %#llx\n",
\r
468 return err ? err : -EINVAL;
\r
471 // pr_info("verifying 1st page of block %d\n", ebnum);
\r
472 if (memcmp(writebuf, readbuf, pgsize)) {
\r
473 pr_err("2.18 verify failed!\n");
\r
477 // pr_info("erasing block %d\n", ebnum);
\r
478 err = mtd_test_erase_eraseblock(ebnum, 0);
\r
482 // pr_info("writing 1st page of block %d\n", ebnum);
\r
483 prandom_bytes_state(&rnd_state, writebuf, pgsize);
\r
484 strcpy(writebuf, "There is no data like this!");
\r
485 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
\r
486 if (err || written != pgsize) {
\r
487 pr_err("2.19 error: write failed at %#llx\n",
\r
489 return err ? err : -EINVAL;
\r
492 // pr_info("erasing block %d\n", ebnum2);
\r
493 err = mtd_test_erase_eraseblock(ebnum2, 0);
\r
497 // pr_info("reading 1st page of block %d\n", ebnum);
\r
498 memset(readbuf, 0, pgsize);
\r
499 err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
\r
500 if (mtd_is_bitflip(err))
\r
502 if (err || read != pgsize) {
\r
503 pr_err("2.20 error: read failed at %#llx\n",
\r
505 return err ? err : -EINVAL;
\r
508 // pr_info("verifying 1st page of block %d\n", ebnum);
\r
509 if (memcmp(writebuf, readbuf, pgsize)) {
\r
510 pr_err("2.21 verify failed!\n");
\r
515 // pr_info("erasecrosstest ok\n");
\r
519 static int pagetest_erasetest(void)
\r
523 size_t read = 0, written = 0;
\r
524 unsigned int i = 0, ebnum = 0, ok = 1;
\r
526 // pr_info("erasetest\n");
\r
530 for (i = 0; i < ebcnt && bbt[i]; ++i) {
\r
531 addr0 += mtd->erasesize;
\r
535 // pr_info("erasing block %d\n", ebnum);
\r
536 err = mtd_test_erase_eraseblock(ebnum, 0);
\r
540 // pr_info("writing 1st page of block %d\n", ebnum);
\r
541 prandom_bytes_state(&rnd_state, writebuf, pgsize);
\r
542 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
\r
543 if (err || written != pgsize) {
\r
544 pr_err("2.22 error: write failed at %#llx\n",
\r
546 return err ? err : -EINVAL;
\r
549 // pr_info("erasing block %d\n", ebnum);
\r
550 err = mtd_test_erase_eraseblock(ebnum, 0);
\r
554 // pr_info("reading 1st page of block %d\n", ebnum);
\r
555 err = mtd_read(mtd, addr0, pgsize, &read, twopages);
\r
556 if (mtd_is_bitflip(err))
\r
558 if (err || read != pgsize) {
\r
559 pr_err("2.23 error: read failed at %#llx\n",
\r
561 return err ? err : -EINVAL;
\r
564 // pr_info("verifying 1st page of block %d is all 0xff\n", ebnum);
\r
565 for (i = 0; i < pgsize; ++i)
\r
566 if (twopages[i] != 0xff) {
\r
567 pr_err("2.24 verifying all 0xff failed at %d\n",
\r
574 // pr_info("erasetest ok\n");
\r
579 static int mtd_test_pagetest(void)
\r
582 unsigned int i = 0;
\r
584 bufsize = mtd->writesize * 2;
\r
585 writebuf = kzalloc(mtd->erasesize, GFP_KERNEL);
\r
587 pr_err("error: alloc writebuf failed!\n");
\r
591 twopages = kzalloc(bufsize, GFP_KERNEL);
\r
593 pr_err("error: alloc twopages failed!\n");
\r
597 boundary = kzalloc(bufsize, GFP_KERNEL);
\r
599 pr_err("error: alloc boundary failed!\n");
\r
603 pr_info("pagetest begin!\n");
\r
605 err = mtd_test_erase_whole_device();
\r
609 prandom_seed_state(&rnd_state, 1);
\r
610 for (i = 0; i < ebcnt; ++i) {
\r
613 err = pagetest_write_eraseblock(i);
\r
619 prandom_seed_state(&rnd_state, 1);
\r
620 for (i = 0; i < ebcnt; ++i) {
\r
623 err = pagetest_verify_eraseblock(i);
\r
629 err = pagetest_crosstest();
\r
633 err = pagetest_erasecrosstest();
\r
637 err = pagetest_erasetest();
\r
641 pr_info("pagetest finished successfullly!\n");
\r
650 static int subpagetest_write_eraseblock(int ebnum)
\r
653 size_t written = 0;
\r
654 loff_t addr = ebnum * mtd->erasesize;
\r
656 prandom_bytes_state(&rnd_state, writebuf, subpgsize);
\r
657 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
\r
658 if (unlikely(err || written != subpgsize)) {
\r
659 pr_err("error: write failed at %#llx, err: %d, written: %d\n",
\r
660 (long long)addr, err, written);
\r
661 return err ? err : -EINVAL;
\r
665 prandom_bytes_state(&rnd_state, writebuf, subpgsize);
\r
666 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
\r
667 if (unlikely(err || written != subpgsize)) {
\r
668 pr_err("error: write failed at %#llx, err: %d, written: %d\n",
\r
669 (long long)addr, err, written);
\r
670 return err ? err : -EINVAL;
\r
676 static int subpagetest_write_eraseblock2(int ebnum)
\r
679 size_t written = 0;
\r
680 unsigned int k = 0;
\r
681 loff_t addr = ebnum * mtd->erasesize;
\r
683 for (k = 1; k < 33; ++k) {
\r
684 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
\r
686 prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
\r
687 err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
\r
688 if (unlikely(err || written != subpgsize * k)) {
\r
689 pr_err("error: write failed at %#llx, err: %d, written: %d\n",
\r
690 (long long)addr, err, written);
\r
691 return err ? err : -EINVAL;
\r
693 addr += subpgsize * k;
\r
699 static int subpagetest_verify_eraseblock(int ebnum)
\r
703 loff_t addr = ebnum * mtd->erasesize;
\r
705 prandom_bytes_state(&rnd_state, writebuf, subpgsize);
\r
706 memset(readbuf, 0, subpgsize);
\r
707 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
\r
708 if (unlikely(err || read != subpgsize)) {
\r
709 if (mtd_is_bitflip(err) && read == subpgsize) {
\r
710 pr_info("ECC correction at %#llx\n",
\r
714 pr_err("error: read failed at %#llx\n",
\r
716 return err ? err : -EINVAL;
\r
719 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
\r
720 pr_err("error: verify failed at %#llx\n",
\r
722 pr_info("------------- written----------------\n");
\r
723 mtd_test_dump_buf(writebuf, subpgsize, 32);
\r
724 pr_info("------------- read ------------------\n");
\r
725 mtd_test_dump_buf(readbuf, subpgsize, 32);
\r
726 pr_info("-------------------------------------\n");
\r
731 prandom_bytes_state(&rnd_state, writebuf, subpgsize);
\r
732 memset(readbuf, 0, subpgsize);
\r
733 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
\r
734 if (unlikely(err || read != subpgsize)) {
\r
735 if (mtd_is_bitflip(err) && read == subpgsize) {
\r
736 pr_info("ECC correction at %#llx\n",
\r
740 pr_err("error: read failed at %#llx\n",
\r
742 return err ? err : -EINVAL;
\r
745 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
\r
746 pr_info("error: verify failed at %#llx\n",
\r
748 pr_info("------------- written----------------\n");
\r
749 mtd_test_dump_buf(writebuf, subpgsize, 32);
\r
750 pr_info("------------- read ------------------\n");
\r
751 mtd_test_dump_buf(readbuf, subpgsize, 32);
\r
752 pr_info("-------------------------------------\n");
\r
759 static int subpagetest_verify_eraseblock2(int ebnum)
\r
763 unsigned int k = 0;
\r
764 loff_t addr = ebnum * mtd->erasesize;
\r
766 for (k = 1; k < 33; ++k) {
\r
767 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
\r
769 prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
\r
770 memset(readbuf, 0, subpgsize * k);
\r
771 err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
\r
772 if (unlikely(err || read != subpgsize * k)) {
\r
773 if (mtd_is_bitflip(err) && read == subpgsize * k) {
\r
774 pr_info("ECC correction at %#llx\n",
\r
778 pr_err("error: read failed at "
\r
779 "%#llx\n", (long long)addr);
\r
780 return err ? err : -EINVAL;
\r
783 if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
\r
784 pr_err("error: verify failed at %#llx\n",
\r
788 addr += subpgsize * k;
\r
794 static int subpagetest_verify_eraseblock_ff(int ebnum)
\r
799 loff_t addr = ebnum * mtd->erasesize;
\r
801 memset(writebuf, 0xff, subpgsize);
\r
802 for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
\r
803 memset(readbuf, 0, subpgsize);
\r
804 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
\r
805 if (unlikely(err || read != subpgsize)) {
\r
806 if (mtd_is_bitflip(err) && read == subpgsize) {
\r
807 pr_info("ECC correction at %#llx\n",
\r
811 pr_err("error: read failed at "
\r
812 "%#llx\n", (long long)addr);
\r
813 return err ? err : -EINVAL;
\r
816 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
\r
817 pr_err("error: verify 0xff failed at "
\r
818 "%#llx\n", (long long)addr);
\r
827 static int subpagetest_verify_all_eraseblocks_ff(void)
\r
830 unsigned int i = 0;
\r
832 // pr_info("verifying all eraseblocks for 0xff\n");
\r
833 for (i = 0; i < ebcnt; ++i) {
\r
836 err = subpagetest_verify_eraseblock_ff(i);
\r
841 // pr_info("verified %u eraseblocks\n", i);
\r
845 static int mtd_test_subpagetest(void)
\r
848 unsigned int i = 0;
\r
850 writebuf = kmalloc(32 * subpgsize, GFP_KERNEL);
\r
852 pr_err("Error: cannot allocate enough memory!\n");
\r
856 readbuf = kmalloc(32 * subpgsize, GFP_KERNEL);
\r
858 pr_err("Error: cannot allocate enough memory!\n");
\r
862 pr_info("subpagetest begin!\n");
\r
863 err = mtd_test_erase_whole_device();
\r
867 // pr_info("writing whole device\n");
\r
868 prandom_seed_state(&rnd_state, 1);
\r
869 for (i = 0; i < ebcnt; ++i) {
\r
872 err = subpagetest_write_eraseblock(i);
\r
877 // pr_info("written %u eraseblocks\n", i);
\r
879 prandom_seed_state(&rnd_state, 1);
\r
880 // pr_info("verifying all eraseblocks\n");
\r
881 for (i = 0; i < ebcnt; ++i) {
\r
884 err = subpagetest_verify_eraseblock(i);
\r
889 // pr_info("verified %u eraseblocks\n", i);
\r
891 err = mtd_test_erase_whole_device();
\r
895 err = subpagetest_verify_all_eraseblocks_ff();
\r
899 /* Write all eraseblocks */
\r
900 prandom_seed_state(&rnd_state, 3);
\r
901 // pr_info("writing whole device\n");
\r
902 for (i = 0; i < ebcnt; ++i) {
\r
905 err = subpagetest_write_eraseblock2(i);
\r
910 // pr_info("written %u eraseblocks\n", i);
\r
912 /* Check all eraseblocks */
\r
913 prandom_seed_state(&rnd_state, 3);
\r
914 // pr_info("verifying all eraseblocks\n");
\r
915 for (i = 0; i < ebcnt; ++i) {
\r
918 err = subpagetest_verify_eraseblock2(i);
\r
923 // pr_info("verified %u eraseblocks\n", i);
\r
925 err = mtd_test_erase_whole_device();
\r
929 err = subpagetest_verify_all_eraseblocks_ff();
\r
933 pr_info("subpagetest finished successfully!\n");
\r
941 static void oobtest_do_vary_offset(void)
\r
946 if (use_offset >= use_len_max)
\r
948 use_len = use_len_max - use_offset;
\r
952 static int oobtest_write_eraseblock(int ebnum)
\r
955 unsigned int i = 0;
\r
956 struct mtd_oob_ops ops;
\r
957 loff_t addr = ebnum * mtd->erasesize;
\r
959 for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
\r
960 prandom_bytes_state(&rnd_state, writebuf, use_len);
\r
961 ops.mode = MTD_OPS_AUTO_OOB;
\r
964 ops.ooblen = use_len;
\r
966 ops.ooboffs = use_offset;
\r
968 ops.oobbuf = writebuf;
\r
969 err = mtd_write_oob(mtd, addr, &ops);
\r
970 if (err || ops.oobretlen != use_len) {
\r
971 pr_err("error: writeoob failed at %#llx\n",
\r
973 pr_err("error: use_len %d, use_offset %d\n",
\r
974 use_len, use_offset);
\r
976 return err ? err : -1;
\r
979 oobtest_do_vary_offset();
\r
985 static int oobtest_write_whole_device(void)
\r
988 unsigned int i = 1;
\r
990 // pr_info("writing OOBs of whole device\n");
\r
991 for (i = 0; i < ebcnt; ++i) {
\r
994 err = oobtest_write_eraseblock(i);
\r
999 // pr_info("written %u eraseblocks\n", i);
\r
1003 static int oobtest_verify_eraseblock(int ebnum)
\r
1006 unsigned int i = 0;
\r
1007 struct mtd_oob_ops ops = {0};
\r
1008 loff_t addr = ebnum * mtd->erasesize;
\r
1010 for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
\r
1011 prandom_bytes_state(&rnd_state, writebuf, use_len);
\r
1012 ops.mode = MTD_OPS_AUTO_OOB;
\r
1015 ops.ooblen = use_len;
\r
1016 ops.oobretlen = 0;
\r
1017 ops.ooboffs = use_offset;
\r
1018 ops.datbuf = NULL;
\r
1019 ops.oobbuf = readbuf;
\r
1020 err = mtd_read_oob(mtd, addr, &ops);
\r
1021 if (err || ops.oobretlen != use_len) {
\r
1022 pr_err("error: readoob failed at %#llx\n",
\r
1025 return err ? err : -1;
\r
1027 if (memcmp(readbuf, writebuf, use_len)) {
\r
1028 pr_err("error: verify failed at %#llx\n",
\r
1031 if (errcnt > 1000) {
\r
1032 pr_err("error: too many errors\n");
\r
1036 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
\r
1039 ops.mode = MTD_OPS_AUTO_OOB;
\r
1042 ops.ooblen = mtd->ecclayout->oobavail;
\r
1043 ops.oobretlen = 0;
\r
1045 ops.datbuf = NULL;
\r
1046 ops.oobbuf = readbuf;
\r
1047 err = mtd_read_oob(mtd, addr, &ops);
\r
1048 if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
\r
1049 pr_err("error: readoob failed at %#llx\n",
\r
1052 return err ? err : -1;
\r
1054 if (memcmp(readbuf + use_offset, writebuf, use_len)) {
\r
1055 pr_err("error: verify failed at %#llx\n",
\r
1058 if (errcnt > 1000) {
\r
1059 pr_err("error: too many errors\n");
\r
1063 for (k = 0; k < use_offset; ++k)
\r
1064 if (readbuf[k] != 0xff) {
\r
1065 pr_err("error: verify 0xff "
\r
1066 "failed at %#llx\n",
\r
1069 if (errcnt > 1000) {
\r
1070 pr_err("error: too "
\r
1075 for (k = use_offset + use_len;
\r
1076 k < mtd->ecclayout->oobavail; ++k)
\r
1077 if (readbuf[k] != 0xff) {
\r
1078 pr_err("error: verify 0xff "
\r
1079 "failed at %#llx\n",
\r
1082 if (errcnt > 1000) {
\r
1083 pr_err("error: too "
\r
1090 oobtest_do_vary_offset();
\r
1097 adjust the str when mtd->ecclayout->oobavail is not 4bytes alignment
\r
1098 @str:the string need to be adjusted
\r
1099 @str_len:the string's length
\r
1100 @sub_len:mtd->ecclayout->oobavail
\r
1102 static void oobtest_adjust(char *str, unsigned int str_len, unsigned int sub_len)
\r
1105 char *tmp_str = NULL;
\r
1106 unsigned int tmp_len = 0;
\r
1108 tmp_len = ((sub_len >> 2) + 1) << 2;
\r
1109 tmp_str = (char *)vmalloc(str_len);
\r
1111 pr_err("%s, can't get enough memory!\n", __func__);
\r
1115 memcpy(tmp_str, str, str_len);
\r
1116 memset(str, 0, str_len);
\r
1118 for(i = 0; i < str_len/tmp_len; i++)
\r
1120 memcpy(str + (sub_len * i), tmp_str + (tmp_len * i), sub_len);
\r
1126 static int oobtest_verify_eraseblock_in_one_go(int ebnum)
\r
1129 struct mtd_oob_ops ops = {0};
\r
1130 loff_t addr = ebnum * mtd->erasesize;
\r
1131 size_t len = mtd->ecclayout->oobavail * pgcnt;
\r
1133 prandom_bytes_state(&rnd_state, writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * pgcnt);
\r
1134 if(mtd->ecclayout->oobavail%4 != 0)
\r
1135 oobtest_adjust(writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * pgcnt, mtd->ecclayout->oobavail);
\r
1136 ops.mode = MTD_OPS_AUTO_OOB;
\r
1140 ops.oobretlen = 0;
\r
1142 ops.datbuf = NULL;
\r
1143 ops.oobbuf = readbuf;
\r
1144 err = mtd_read_oob(mtd, addr, &ops);
\r
1145 if (err || ops.oobretlen != len) {
\r
1146 pr_err("error: readoob failed at %#llx\n",
\r
1149 return err ? err : -1;
\r
1151 if (memcmp(readbuf, writebuf, len)) {
\r
1152 pr_err("error: verify failed at %#llx\n",
\r
1155 if (errcnt > 1000) {
\r
1156 pr_err("error: too many errors\n");
\r
1164 static int oobtest_verify_all_eraseblocks(void)
\r
1167 unsigned int i = 0;
\r
1169 // pr_info("verifying all eraseblocks\n");
\r
1170 for (i = 0; i < ebcnt; ++i) {
\r
1173 err = oobtest_verify_eraseblock(i);
\r
1178 // pr_info("verified %u eraseblocks\n", i);
\r
1182 static int mtd_test_oobtest(void)
\r
1185 unsigned int i = 0;
\r
1186 loff_t addr = 0, addr0 = 0;
\r
1187 struct mtd_oob_ops ops = {0};
\r
1190 readbuf = vmalloc(mtd->erasesize);
\r
1192 pr_err("error: alloc readbuf failed!\n");
\r
1195 writebuf = vmalloc(mtd->erasesize);
\r
1197 pr_err("error: alloc writebuf failed!\n");
\r
1202 use_len = mtd->ecclayout->oobavail;
\r
1203 use_len_max = mtd->ecclayout->oobavail;
\r
1205 pr_info("oobtest begin!\n");
\r
1207 /* First test: write all OOB, read it back and verify */
\r
1208 pr_info("test 1 of 5\n");
\r
1210 err = mtd_test_erase_whole_device();
\r
1214 prandom_seed_state(&rnd_state, 1);
\r
1215 err = oobtest_write_whole_device();
\r
1219 prandom_seed_state(&rnd_state, 1);
\r
1220 err = oobtest_verify_all_eraseblocks();
\r
1225 * Second test: write all OOB, a block at a time, read it back and
\r
1228 pr_info("test 2 of 5\n");
\r
1230 err = mtd_test_erase_whole_device();
\r
1234 prandom_seed_state(&rnd_state, 3);
\r
1235 err = oobtest_write_whole_device();
\r
1239 /* Check all eraseblocks */
\r
1240 prandom_seed_state(&rnd_state, 3);
\r
1241 // pr_info("verifying all eraseblocks\n");
\r
1242 for (i = 0; i < ebcnt; ++i) {
\r
1245 err = oobtest_verify_eraseblock_in_one_go(i);
\r
1250 // pr_info("verified %u eraseblocks\n", i);
\r
1253 * Third test: write OOB at varying offsets and lengths, read it back
\r
1256 pr_info("test 3 of 5\n");
\r
1258 err = mtd_test_erase_whole_device();
\r
1262 /* Write all eraseblocks */
\r
1264 use_len = mtd->ecclayout->oobavail;
\r
1265 use_len_max = mtd->ecclayout->oobavail;
\r
1267 prandom_seed_state(&rnd_state, 5);
\r
1269 err = oobtest_write_whole_device();
\r
1273 /* Check all eraseblocks */
\r
1275 use_len = mtd->ecclayout->oobavail;
\r
1276 use_len_max = mtd->ecclayout->oobavail;
\r
1278 prandom_seed_state(&rnd_state, 5);
\r
1279 err = oobtest_verify_all_eraseblocks();
\r
1284 use_len = mtd->ecclayout->oobavail;
\r
1285 use_len_max = mtd->ecclayout->oobavail;
\r
1288 /* Fourth test: try to write off end of device */
\r
1289 pr_info("test 4 of 5\n");
\r
1291 err = mtd_test_erase_whole_device();
\r
1296 for (i = 0; i < ebcnt && bbt[i]; ++i)
\r
1297 addr0 += mtd->erasesize;
\r
1299 /* Attempt to write off end of OOB */
\r
1300 ops.mode = MTD_OPS_AUTO_OOB;
\r
1304 ops.oobretlen = 0;
\r
1305 ops.ooboffs = mtd->ecclayout->oobavail;
\r
1306 ops.datbuf = NULL;
\r
1307 ops.oobbuf = writebuf;
\r
1308 pr_info("attempting to start write past end of OOB\n");
\r
1309 pr_info("an error is expected...\n");
\r
1310 err = mtd_write_oob(mtd, addr0, &ops);
\r
1312 pr_info("error occurred as expected\n");
\r
1315 pr_info("error: can write past end of OOB\n");
\r
1319 /* Attempt to read off end of OOB */
\r
1320 ops.mode = MTD_OPS_AUTO_OOB;
\r
1324 ops.oobretlen = 0;
\r
1325 ops.ooboffs = mtd->ecclayout->oobavail;
\r
1326 ops.datbuf = NULL;
\r
1327 ops.oobbuf = readbuf;
\r
1328 pr_info("attempting to start read past end of OOB\n");
\r
1329 pr_info("an error is expected...\n");
\r
1330 err = mtd_read_oob(mtd, addr0, &ops);
\r
1332 pr_info("error occurred as expected\n");
\r
1335 pr_err("error: can read past end of OOB\n");
\r
1339 if (bbt[ebcnt - 1])
\r
1340 pr_info("skipping end of device tests because last "
\r
1341 "block is bad\n");
\r
1343 /* Attempt to write off end of device */
\r
1344 ops.mode = MTD_OPS_AUTO_OOB;
\r
1347 ops.ooblen = mtd->ecclayout->oobavail + 1;
\r
1348 ops.oobretlen = 0;
\r
1350 ops.datbuf = NULL;
\r
1351 ops.oobbuf = writebuf;
\r
1352 pr_info("attempting to write past end of device\n");
\r
1353 pr_info("an error is expected...\n");
\r
1354 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
\r
1356 pr_info("error occurred as expected\n");
\r
1359 pr_err("error: wrote past end of device\n");
\r
1363 /* Attempt to read off end of device */
\r
1364 ops.mode = MTD_OPS_AUTO_OOB;
\r
1367 ops.ooblen = mtd->ecclayout->oobavail + 1;
\r
1368 ops.oobretlen = 0;
\r
1370 ops.datbuf = NULL;
\r
1371 ops.oobbuf = readbuf;
\r
1372 pr_info("attempting to read past end of device\n");
\r
1373 pr_info("an error is expected...\n");
\r
1374 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
\r
1376 pr_info("error occurred as expected\n");
\r
1379 pr_err("error: read past end of device\n");
\r
1383 err = mtd_test_erase_eraseblock(ebcnt - 1, 0);
\r
1387 /* Attempt to write off end of device */
\r
1388 ops.mode = MTD_OPS_AUTO_OOB;
\r
1391 ops.ooblen = mtd->ecclayout->oobavail;
\r
1392 ops.oobretlen = 0;
\r
1394 ops.datbuf = NULL;
\r
1395 ops.oobbuf = writebuf;
\r
1396 pr_info("attempting to write past end of device\n");
\r
1397 pr_info("an error is expected...\n");
\r
1398 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
\r
1400 pr_info("error occurred as expected\n");
\r
1403 pr_err("error: wrote past end of device\n");
\r
1407 /* Attempt to read off end of device */
\r
1408 ops.mode = MTD_OPS_AUTO_OOB;
\r
1411 ops.ooblen = mtd->ecclayout->oobavail;
\r
1412 ops.oobretlen = 0;
\r
1414 ops.datbuf = NULL;
\r
1415 ops.oobbuf = readbuf;
\r
1416 pr_info("attempting to read past end of device\n");
\r
1417 pr_info("an error is expected...\n");
\r
1418 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
\r
1420 pr_info("error occurred as expected\n");
\r
1423 pr_err("error: read past end of device\n");
\r
1428 /* Fifth test: write / read across block boundaries */
\r
1429 pr_info("test 5 of 5\n");
\r
1431 /* Erase all eraseblocks */
\r
1432 err = mtd_test_erase_whole_device();
\r
1436 /* Write all eraseblocks */
\r
1437 prandom_seed_state(&rnd_state, 11);
\r
1438 // pr_info("writing OOBs of whole device\n");
\r
1439 for (i = 0; i < ebcnt - 1; ++i) {
\r
1442 size_t sz = mtd->ecclayout->oobavail;
\r
1443 if (bbt[i] || bbt[i + 1])
\r
1445 addr = (i + 1) * mtd->erasesize - mtd->writesize;
\r
1446 for (pg = 0; pg < cnt; ++pg) {
\r
1447 prandom_bytes_state(&rnd_state, writebuf, sz);
\r
1448 ops.mode = MTD_OPS_AUTO_OOB;
\r
1452 ops.oobretlen = 0;
\r
1454 ops.datbuf = NULL;
\r
1455 ops.oobbuf = writebuf;
\r
1456 err = mtd_write_oob(mtd, addr, &ops);
\r
1460 addr += mtd->writesize;
\r
1463 // pr_info("written %u eraseblocks\n", i);
\r
1465 /* Check all eraseblocks */
\r
1466 prandom_seed_state(&rnd_state, 11);
\r
1467 // pr_info("verifying all eraseblocks\n");
\r
1468 for (i = 0; i < ebcnt - 1; ++i) {
\r
1469 if (bbt[i] || bbt[i + 1])
\r
1471 prandom_bytes_state(&rnd_state, writebuf,
\r
1472 (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * 2);
\r
1473 if(mtd->ecclayout->oobavail%4 != 0)
\r
1474 oobtest_adjust(writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * 2, mtd->ecclayout->oobavail);
\r
1475 addr = (i + 1) * mtd->erasesize - mtd->writesize;
\r
1476 ops.mode = MTD_OPS_AUTO_OOB;
\r
1479 ops.ooblen = mtd->ecclayout->oobavail * 2;
\r
1480 ops.oobretlen = 0;
\r
1482 ops.datbuf = NULL;
\r
1483 ops.oobbuf = readbuf;
\r
1484 err = mtd_read_oob(mtd, addr, &ops);
\r
1487 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
\r
1488 pr_err("error: verify failed at %#llx\n",
\r
1491 if (errcnt > 1000) {
\r
1492 pr_err("error: too many errors\n");
\r
1498 // pr_info("verified %u eraseblocks\n", i);
\r
1500 pr_info("oobtest finished with %d errors!\n", errcnt);
\r
1508 static long speedtest_calc_speed(void)
\r
1513 ms = (finish.tv_sec - start.tv_sec) * 1000 +
\r
1514 (finish.tv_usec - start.tv_usec) / 1000;
\r
1517 k = goodebcnt * (mtd->erasesize / 1024) * 1000;
\r
1522 static int speedtest_write_eraseblock(int ebnum)
\r
1525 size_t written = 0;
\r
1526 loff_t addr = ebnum * mtd->erasesize;
\r
1528 err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
\r
1529 if (err || written != mtd->erasesize) {
\r
1530 pr_err("error: write failed at %#llx\n", addr);
\r
1538 static int speedtest_write_eraseblock_by_page(int ebnum)
\r
1541 size_t written = 0;
\r
1542 unsigned int i = 0;
\r
1543 void *buf = writebuf;
\r
1544 loff_t addr = ebnum * mtd->erasesize;
\r
1546 for (i = 0; i < pgcnt; i++) {
\r
1547 err = mtd_write(mtd, addr, pgsize, &written, buf);
\r
1548 if (err || written != pgsize) {
\r
1549 pr_err("error: write failed at %#llx\n",
\r
1562 static int speedtest_write_eraseblock_by_2pages(int ebnum)
\r
1565 void *buf = writebuf;
\r
1566 unsigned int i = 0, n = pgcnt / 2;
\r
1567 size_t written = 0, sz = pgsize * 2;
\r
1568 loff_t addr = ebnum * mtd->erasesize;
\r
1570 for (i = 0; i < n; i++) {
\r
1571 err = mtd_write(mtd, addr, sz, &written, buf);
\r
1572 if (err || written != sz) {
\r
1573 pr_err("error: write failed at %#llx\n",
\r
1583 err = mtd_write(mtd, addr, pgsize, &written, buf);
\r
1584 if (err || written != pgsize) {
\r
1585 pr_err("error: write failed at %#llx\n",
\r
1595 static int speedtest_read_eraseblock(int ebnum)
\r
1599 loff_t addr = ebnum * mtd->erasesize;
\r
1601 err = mtd_read(mtd, addr, mtd->erasesize, &read, writebuf);
\r
1602 /* Ignore corrected ECC errors */
\r
1603 if (mtd_is_bitflip(err))
\r
1605 if (err || read != mtd->erasesize) {
\r
1606 pr_err("error: read failed at %#llx\n", addr);
\r
1614 static int speedtest_read_eraseblock_by_page(int ebnum)
\r
1618 unsigned int i = 0;
\r
1619 void *buf = writebuf;
\r
1620 loff_t addr = ebnum * mtd->erasesize;
\r
1622 for (i = 0; i < pgcnt; i++) {
\r
1623 err = mtd_read(mtd, addr, pgsize, &read, buf);
\r
1624 /* Ignore corrected ECC errors */
\r
1625 if (mtd_is_bitflip(err))
\r
1627 if (err || read != pgsize) {
\r
1628 pr_err("error: read failed at %#llx\n",
\r
1641 static int speedtest_read_eraseblock_by_2pages(int ebnum)
\r
1644 void *buf = writebuf;
\r
1645 size_t read = 0, sz = pgsize * 2;
\r
1646 unsigned int i = 0, n = pgcnt / 2;
\r
1647 loff_t addr = ebnum * mtd->erasesize;
\r
1649 for (i = 0; i < n; i++) {
\r
1650 err = mtd_read(mtd, addr, sz, &read, buf);
\r
1651 /* Ignore corrected ECC errors */
\r
1652 if (mtd_is_bitflip(err))
\r
1654 if (err || read != sz) {
\r
1655 pr_err("error: read failed at %#llx\n",
\r
1665 err = mtd_read(mtd, addr, pgsize, &read, buf);
\r
1666 /* Ignore corrected ECC errors */
\r
1667 if (mtd_is_bitflip(err))
\r
1669 if (err || read != pgsize) {
\r
1670 pr_err("error: read failed at %#llx\n",
\r
1680 static int mtd_test_speedtest(void )
\r
1684 unsigned int i = 0, blocks = 0, j = 0, k = 0;
\r
1686 writebuf = vmalloc(mtd->erasesize);
\r
1688 pr_err("%s, can't get enough memory!\n", __func__);
\r
1692 memset(writebuf, 0, mtd->erasesize);
\r
1693 prandom_bytes(writebuf, mtd->erasesize);
\r
1695 pr_info("speedtest begin!\n");
\r
1696 err = mtd_test_erase_whole_device();
\r
1700 /* Write all eraseblocks, 1 eraseblock at a time */
\r
1701 // pr_info("testing eraseblock write speed\n");
\r
1702 mtd_test_start_timing();
\r
1703 for (i = 0; i < ebcnt; ++i) {
\r
1706 err = speedtest_write_eraseblock(i);
\r
1711 mtd_test_stop_timing();
\r
1712 speed = speedtest_calc_speed();
\r
1713 pr_info("eraseblock write speed is %ld KiB/s\n", speed);
\r
1715 /* Read all eraseblocks, 1 eraseblock at a time */
\r
1716 // pr_info("testing eraseblock read speed\n");
\r
1717 mtd_test_start_timing();
\r
1718 for (i = 0; i < ebcnt; ++i) {
\r
1721 err = speedtest_read_eraseblock(i);
\r
1726 mtd_test_stop_timing();
\r
1727 speed = speedtest_calc_speed();
\r
1728 pr_info("eraseblock read speed is %ld KiB/s\n", speed);
\r
1730 err = mtd_test_erase_whole_device();
\r
1734 /* Write all eraseblocks, 1 page at a time */
\r
1735 // pr_info("testing page write speed\n");
\r
1736 mtd_test_start_timing();
\r
1737 for (i = 0; i < ebcnt; ++i) {
\r
1740 err = speedtest_write_eraseblock_by_page(i);
\r
1745 mtd_test_stop_timing();
\r
1746 speed = speedtest_calc_speed();
\r
1747 pr_info("page write speed is %ld KiB/s\n", speed);
\r
1749 /* Read all eraseblocks, 1 page at a time */
\r
1750 // pr_info("testing page read speed\n");
\r
1751 mtd_test_start_timing();
\r
1752 for (i = 0; i < ebcnt; ++i) {
\r
1755 err = speedtest_read_eraseblock_by_page(i);
\r
1760 mtd_test_stop_timing();
\r
1761 speed = speedtest_calc_speed();
\r
1762 pr_info("page read speed is %ld KiB/s\n", speed);
\r
1764 err = mtd_test_erase_whole_device();
\r
1768 /* Write all eraseblocks, 2 pages at a time */
\r
1769 // pr_info("testing 2 page write speed\n");
\r
1770 mtd_test_start_timing();
\r
1771 for (i = 0; i < ebcnt; ++i) {
\r
1774 err = speedtest_write_eraseblock_by_2pages(i);
\r
1779 mtd_test_stop_timing();
\r
1780 speed = speedtest_calc_speed();
\r
1781 pr_info("2 page write speed is %ld KiB/s\n", speed);
\r
1783 /* Read all eraseblocks, 2 pages at a time */
\r
1784 // pr_info("testing 2 page read speed\n");
\r
1785 mtd_test_start_timing();
\r
1786 for (i = 0; i < ebcnt; ++i) {
\r
1789 err = speedtest_read_eraseblock_by_2pages(i);
\r
1794 mtd_test_stop_timing();
\r
1795 speed = speedtest_calc_speed();
\r
1796 pr_info("2 page read speed is %ld KiB/s\n", speed);
\r
1798 /* Erase all eraseblocks */
\r
1799 // pr_info("Testing erase speed\n");
\r
1800 mtd_test_start_timing();
\r
1801 for (i = 0; i < ebcnt; ++i) {
\r
1804 err = mtd_test_erase_eraseblock(i, 0);
\r
1809 mtd_test_stop_timing();
\r
1810 speed = speedtest_calc_speed();
\r
1811 pr_info("erase speed is %ld KiB/s\n", speed);
\r
1813 /* Multi-block erase all eraseblocks */
\r
1814 for (k = 1; k < 7; k++) {
\r
1816 // pr_info("Testing %dx multi-block erase speed\n", blocks);
\r
1817 mtd_test_start_timing();
\r
1818 for (i = 0; i < ebcnt; ) {
\r
1819 for (j = 0; j < blocks && (i + j) < ebcnt; j++)
\r
1826 err = mtd_test_erase_eraseblock(i, j);
\r
1832 mtd_test_stop_timing();
\r
1833 speed = speedtest_calc_speed();
\r
1834 pr_info("%dx multi-block erase speed is %ld KiB/s\n",
\r
1837 pr_info("speedtest finished successfully!\n");
\r
1844 static int stresstest_rand_eb(void)
\r
1846 unsigned int eb = 0;
\r
1849 eb = prandom_u32();
\r
1850 /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
\r
1851 eb %= (ebcnt - 1);
\r
1857 static int stresstest_rand_offs(void)
\r
1859 unsigned int offs = 0;
\r
1861 offs = prandom_u32();
\r
1866 static int stresstest_rand_len(int offs)
\r
1868 unsigned int len = 0;
\r
1870 len = prandom_u32();
\r
1871 len %= (bufsize - offs);
\r
1875 static int stresstest_do_read(void)
\r
1880 int eb = stresstest_rand_eb();
\r
1881 int offs = stresstest_rand_offs();
\r
1882 int len = stresstest_rand_len(offs);
\r
1884 if (bbt[eb + 1]) {
\r
1885 if (offs >= mtd->erasesize)
\r
1886 offs -= mtd->erasesize;
\r
1887 if (offs + len > mtd->erasesize)
\r
1888 len = mtd->erasesize - offs;
\r
1890 addr = eb * mtd->erasesize + offs;
\r
1891 err = mtd_read(mtd, addr, len, &read, readbuf);
\r
1892 if (mtd_is_bitflip(err))
\r
1894 if (unlikely(err || read != len)) {
\r
1895 pr_err("error: read failed at 0x%llx, err:%d len: %dread:%d\n",
\r
1896 (long long)addr, err, len, read);
\r
1904 static int stresstest_do_write(void)
\r
1908 size_t written = 0;
\r
1909 int eb = stresstest_rand_eb();
\r
1910 unsigned int offs = 0, len = 0;
\r
1912 offs = offsets[eb];
\r
1913 if (offs >= mtd->erasesize) {
\r
1914 err = mtd_test_erase_eraseblock(eb, 0);
\r
1917 offs = offsets[eb] = 0;
\r
1919 len = stresstest_rand_len(offs);
\r
1920 len = ((len + pgsize - 1) / pgsize) * pgsize;
\r
1921 if (offs + len > mtd->erasesize) {
\r
1923 len = mtd->erasesize - offs;
\r
1925 err = mtd_test_erase_eraseblock(eb + 1, 0);
\r
1928 offsets[eb + 1] = 0;
\r
1931 addr = eb * mtd->erasesize + offs;
\r
1932 err = mtd_write(mtd, addr, len, &written, writebuf);
\r
1933 if (unlikely(err || written != len)) {
\r
1934 pr_err("error: write failed at 0x%llx\n",
\r
1941 while (offs > mtd->erasesize) {
\r
1942 offsets[eb++] = mtd->erasesize;
\r
1943 offs -= mtd->erasesize;
\r
1945 offsets[eb] = offs;
\r
1949 static int stresstest_do_operation(void)
\r
1951 if (prandom_u32() & 1) {
\r
1952 return stresstest_do_read();
\r
1954 return stresstest_do_write();
\r
1958 static int mtd_test_stresstest(void)
\r
1961 unsigned int i = 0, op = 0;
\r
1963 bufsize = mtd->erasesize * 2;
\r
1964 readbuf = vmalloc(bufsize);
\r
1966 pr_err("%s, alloc readbuf failed!\n", __func__);
\r
1969 writebuf = vmalloc(bufsize);
\r
1971 pr_err("%s, alloc writebuf failed!\n", __func__);
\r
1975 offsets = vmalloc(ebcnt * sizeof(int));
\r
1977 pr_err("%s, alloc offsets failed!\n", __func__);
\r
1982 pr_info("stresstest begin!\n");
\r
1984 for (i = 0; i < ebcnt; i++)
\r
1985 offsets[i] = mtd->erasesize;
\r
1986 prandom_bytes(writebuf, bufsize);
\r
1988 err = mtd_test_erase_whole_device();
\r
1992 for (op = 0; op < 10000; op++) {
\r
1993 if ((op & 1023) == 0)
\r
1994 pr_info("%d operations done\n", op);
\r
1995 err = stresstest_do_operation();
\r
2005 pr_info("stresstest finished, %d operations done!\n", op);
\r
2009 static int __init nandflash_stdtest_init(void)
\r
2014 pr_info(KERN_INFO "\n");
\r
2015 pr_info(KERN_INFO "=================================================\n");
\r
2018 pr_info("Please specify a valid mtd-device via module parameter\n");
\r
2022 pr_info("MTD device: %d\n", dev);
\r
2024 mtd = get_mtd_device(NULL, dev);
\r
2025 if (IS_ERR(mtd)) {
\r
2026 err = PTR_ERR(mtd);
\r
2027 pr_info("error: cannot get MTD device\n");
\r
2031 if (mtd->type != MTD_NANDFLASH) {
\r
2032 pr_info("this test requires NAND flash\n");
\r
2037 do_div(tmp, mtd->erasesize);
\r
2039 pgcnt = mtd->erasesize / mtd->writesize;
\r
2040 pgsize = mtd->writesize;
\r
2041 subsize = mtd->writesize >> mtd->subpage_sft;
\r
2042 subcount = mtd->writesize / subsize;
\r
2043 subpgsize = mtd->writesize >> mtd->subpage_sft;
\r
2045 pr_info("MTD device size %llu, eraseblock size %u, "
\r
2046 "page size %u, count of eraseblocks %u, pages per "
\r
2047 "eraseblock %u, OOB size %u\n",
\r
2048 (unsigned long long)mtd->size, mtd->erasesize,
\r
2049 mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
\r
2051 err = mtd_test_scan_bad_block();
\r
2055 err = mtd_test_readtest();
\r
2057 pr_err("readtest failed!\n");
\r
2061 err = mtd_test_pagetest();
\r
2063 pr_err("pagetest failed!\n");
\r
2067 err = mtd_test_subpagetest();
\r
2069 pr_err("subpagetest failed!\n");
\r
2073 err = mtd_test_oobtest();
\r
2075 pr_err("oobtest failed!\n");
\r
2079 err = mtd_test_speedtest();
\r
2081 pr_err("speedtest failed!\n");
\r
2085 err = mtd_test_stresstest();
\r
2087 pr_err("stresstest failed!\n");
\r
2092 pr_info(KERN_INFO "=================================================\n");
\r
2095 put_mtd_device(mtd);
\r
2100 static void __exit nandflash_stdtest_exit(void)
\r
2105 module_init(nandflash_stdtest_init);
\r
2106 module_exit(nandflash_stdtest_exit);
\r
2108 MODULE_DESCRIPTION("mtd_stdand_test");
\r
2109 MODULE_AUTHOR("ming.tang@spreadtrum.com");
\r
2110 MODULE_LICENSE("GPL");
\r