27 #include <linux/module.h>
31 #include <linux/slab.h>
32 #include <linux/sched.h>
34 #define PRINT_PREF KERN_INFO "mtd_torturetest: "
41 static int ebcnt = 32;
47 MODULE_PARM_DESC(pgcnt,
"number of pages per eraseblock to torture (0 => all)");
53 static int gran = 512;
55 MODULE_PARM_DESC(gran,
"how often the status information should be printed");
61 static unsigned int cycles_count;
64 "(infinite by default)");
69 static unsigned char *patt_5A5;
71 static unsigned char *patt_A5A;
73 static unsigned char *patt_FF;
75 static unsigned char *check_buf;
77 static unsigned int erase_cycles;
82 static void report_corrupt(
unsigned char *
read,
unsigned char *written);
84 static inline void start_timing(
void)
89 static inline void stop_timing(
void)
97 static inline int erase_eraseblock(
int ebnum)
127 static inline int check_eraseblock(
int ebnum,
unsigned char *
buf)
135 addr = (ebnum + 1) * mtd->
erasesize - pgcnt * pgsize;
136 len = pgcnt * pgsize;
140 err =
mtd_read(mtd, addr, len, &read, check_buf);
141 if (mtd_is_bitflip(err))
143 "MTD reported that it was fixed.\n", ebnum);
146 "read %zd\n", err, ebnum, read);
152 "read only %zd, but no error reported\n",
157 if (
memcmp(buf, check_buf, len)) {
159 report_corrupt(check_buf, buf);
181 static inline int write_pattern(
int ebnum,
void *buf)
189 addr = (ebnum + 1) * mtd->
erasesize - pgcnt * pgsize;
190 len = pgcnt * pgsize;
192 err =
mtd_write(mtd, addr, len, &written, buf);
195 " bytes\n", err, ebnum, written);
198 if (written != len) {
200 " reported\n", written, len);
207 static int __init tort_init(
void)
209 int err = 0,
i, infinite = !cycles_count;
213 printk(
KERN_INFO "=================================================\n");
215 "flash, stop it if this is not wanted.\n");
218 printk(
PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
219 printk(
KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
225 ebcnt,
eb,
eb + ebcnt - 1,
dev);
245 if (pgcnt && (pgcnt > mtd->
erasesize / pgsize || pgcnt < 0)) {
281 memset(patt_5A5 +
i * pgsize, 0x55, pgsize);
282 memset(patt_A5A +
i * pgsize, 0xAA, pgsize);
284 memset(patt_5A5 +
i * pgsize, 0xAA, pgsize);
285 memset(patt_A5A +
i * pgsize, 0x55, pgsize);
292 memset(&bad_ebs[0], 0,
sizeof(
int) * ebcnt);
293 if (mtd_can_have_bb(mtd)) {
294 for (
i =
eb;
i <
eb + ebcnt;
i++) {
299 "for EB %d\n", err,
i);
304 printk(
"EB %d is bad. Skip it.\n",
i);
316 for (i =
eb; i <
eb + ebcnt; i++) {
319 err = erase_eraseblock(i);
327 for (i =
eb; i <
eb + ebcnt; i++) {
330 err = check_eraseblock(i, patt_FF);
333 " for 0xFF... pattern\n");
341 for (i =
eb; i <
eb + ebcnt; i++) {
344 if ((
eb + erase_cycles) & 1)
348 err = write_pattern(i, patt);
356 for (i =
eb; i <
eb + ebcnt; i++) {
359 if ((
eb + erase_cycles) & 1)
363 err = check_eraseblock(i, patt);
367 ((
eb + erase_cycles) & 1) ?
368 "0x55AA55..." :
"0xAA55AA...");
377 if (erase_cycles % gran == 0) {
381 ms = (finish.tv_sec -
start.tv_sec) * 1000 +
382 (finish.tv_usec -
start.tv_usec) / 1000;
384 "milliseconds (%lu seconds)\n",
385 erase_cycles, ms, ms / 1000);
389 if (!infinite && --cycles_count == 0)
407 printk(
KERN_INFO "=================================================\n");
412 static void __exit tort_exit(
void)
418 static int countdiffs(
unsigned char *buf,
unsigned char *check_buf,
419 unsigned offset,
unsigned len,
unsigned *bytesp,
421 static void print_bufs(
unsigned char *read,
unsigned char *written,
int start,
428 static void report_corrupt(
unsigned char *read,
unsigned char *written)
436 check_len = pgcnt * pgsize;
438 bytes = bits = pages = 0;
439 for (i = 0; i < check_len; i += pgsize)
440 if (countdiffs(written, read, i, pgsize, &bytes,
447 " what was read from flash and what was expected\n");
449 for (i = 0; i < check_len; i += pgsize) {
452 first = countdiffs(written, read, i, pgsize, &bytes,
457 printk(
"-------------------------------------------------------"
458 "----------------------------------\n");
461 " starting at offset 0x%x\n",
462 (mtd->
erasesize - check_len + i) / pgsize,
465 offset = first & ~0x7;
468 print_bufs(read, written, offset, len);
472 static void print_bufs(
unsigned char *read,
unsigned char *written,
int start,
478 printk(
"Offset Read Written\n");
480 printk(
"0x%08x: ", start + i);
482 for (j1 = 0; j1 < 8 && i + j1 <
len; j1++) {
483 printk(
" %02x", read[start + i + j1]);
484 if (read[start + i + j1] != written[start + i + j1])
495 for (j2 = 0; j2 < 8 && i + j2 <
len; j2++)
496 printk(
" %02x", written[start + i + j2]);
506 static int countdiffs(
unsigned char *buf,
unsigned char *check_buf,
507 unsigned offset,
unsigned len,
unsigned *bytesp,
513 for (i = offset; i < offset +
len; i++)
514 if (buf[i] != check_buf[i]) {
519 while (i < offset + len) {
520 if (buf[i] != check_buf[i]) {
524 if ((buf[i] & bit) != (check_buf[i] & bit))
536 MODULE_AUTHOR(
"Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter");