22 #include <asm/div64.h>
24 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/sched.h>
31 #define PRINT_PREF KERN_INFO "mtd_oobtest: "
38 static unsigned char *readbuf;
39 static unsigned char *writebuf;
40 static unsigned char *bbt;
45 static int use_offset;
47 static int use_len_max;
48 static int vary_offset;
49 static unsigned long next = 1;
51 static inline unsigned int simple_rand(
void)
54 return (
unsigned int)((
next / 65536) % 32768);
57 static inline void simple_srand(
unsigned long seed)
62 static void set_random_data(
unsigned char *
buf,
size_t len)
66 for (i = 0; i < len; ++
i)
67 buf[i] = simple_rand();
70 static int erase_eraseblock(
int ebnum)
96 static int erase_whole_device(
void)
102 for (i = 0; i < ebcnt; ++
i) {
105 err = erase_eraseblock(i);
114 static void do_vary_offset(
void)
119 if (use_offset >= use_len_max)
121 use_len = use_len_max - use_offset;
125 static int write_eraseblock(
int ebnum)
132 for (i = 0; i < pgcnt; ++
i, addr += mtd->
writesize) {
133 set_random_data(writebuf, use_len);
137 ops.ooblen = use_len;
139 ops.ooboffs = use_offset;
141 ops.oobbuf = writebuf;
142 err = mtd_write_oob(mtd, addr, &ops);
143 if (err ||
ops.oobretlen != use_len) {
147 use_len, use_offset);
149 return err ? err : -1;
158 static int write_whole_device(
void)
164 for (i = 0; i < ebcnt; ++
i) {
167 err = write_eraseblock(i);
178 static int verify_eraseblock(
int ebnum)
185 for (i = 0; i < pgcnt; ++
i, addr += mtd->
writesize) {
186 set_random_data(writebuf, use_len);
190 ops.ooblen = use_len;
192 ops.ooboffs = use_offset;
194 ops.oobbuf = readbuf;
196 if (err ||
ops.oobretlen != use_len) {
200 return err ? err : -1;
202 if (
memcmp(readbuf, writebuf, use_len)) {
211 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
221 ops.oobbuf = readbuf;
225 "%#llx\n", (
long long)addr);
227 return err ? err : -1;
229 if (
memcmp(readbuf + use_offset, writebuf, use_len)) {
231 "%#llx\n", (
long long)addr);
239 for (k = 0; k < use_offset; ++
k)
240 if (readbuf[k] != 0xff) {
251 for (k = use_offset + use_len;
253 if (readbuf[k] != 0xff) {
271 static int verify_eraseblock_in_one_go(
int ebnum)
276 size_t len = mtd->
ecclayout->oobavail * pgcnt;
278 set_random_data(writebuf, len);
286 ops.oobbuf = readbuf;
288 if (err ||
ops.oobretlen != len) {
292 return err ? err : -1;
294 if (
memcmp(readbuf, writebuf, len)) {
307 static int verify_all_eraseblocks(
void)
313 for (i = 0; i < ebcnt; ++
i) {
316 err = verify_eraseblock(i);
327 static int is_block_bad(
int ebnum)
338 static int scan_for_bad_eraseblocks(
void)
349 for (i = 0; i < ebcnt; ++
i) {
350 bbt[
i] = is_block_bad(i) ? 1 : 0;
359 static int __init mtd_oobtest_init(
void)
365 loff_t addr = 0, addr0;
368 printk(
KERN_INFO "=================================================\n");
371 printk(
PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
372 printk(
KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
396 "page size %u, count of eraseblocks %u, pages per "
397 "eraseblock %u, OOB size %u\n",
413 err = scan_for_bad_eraseblocks();
425 err = erase_whole_device();
430 err = write_whole_device();
435 err = verify_all_eraseblocks();
445 err = erase_whole_device();
450 err = write_whole_device();
457 for (i = 0; i < ebcnt; ++
i) {
460 err = verify_eraseblock_in_one_go(i);
475 err = erase_whole_device();
486 err = write_whole_device();
496 err = verify_all_eraseblocks();
508 err = erase_whole_device();
513 for (i = 0; i < ebcnt && bbt[
i]; ++
i)
524 ops.oobbuf = writebuf;
527 err = mtd_write_oob(mtd, addr0, &ops);
544 ops.oobbuf = readbuf;
568 ops.oobbuf = writebuf;
588 ops.oobbuf = readbuf;
600 err = erase_eraseblock(ebcnt - 1);
612 ops.oobbuf = writebuf;
632 ops.oobbuf = readbuf;
649 err = erase_whole_device();
656 for (i = 0; i < ebcnt - 1; ++
i) {
660 if (bbt[i] || bbt[i + 1])
664 set_random_data(writebuf, sz);
672 ops.oobbuf = writebuf;
673 err = mtd_write_oob(mtd, addr, &ops);
688 for (i = 0; i < ebcnt - 1; ++
i) {
689 if (bbt[i] || bbt[i + 1])
691 set_random_data(writebuf, mtd->
ecclayout->oobavail * 2);
700 ops.oobbuf = readbuf;
727 printk(
KERN_INFO "=================================================\n");
732 static void __exit mtd_oobtest_exit(
void)