static int __init tort_init(void) { int err = 0, i, infinite = !cycles_count; int bad_ebs[ebcnt]; ; ; // printk(PRINT_PREF "Warning: this program is trying to wear out your " ; ; // printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", ; if (pgcnt) // printk(PRINT_PREF "torturing just %d pages per eraseblock\n", ; ; mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); ; return err; } if (mtd->writesize == 1) { // printk(PRINT_PREF "not NAND flash, assume page size is 512 " ; pgsize = 512; } else pgsize = mtd->writesize; if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { ; goto out_mtd; } err = -ENOMEM; patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_5A5) { ; goto out_mtd; } patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_A5A) { ; goto out_patt_5A5; } patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_FF) { ; goto out_patt_A5A; } check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!check_buf) { ; goto out_patt_FF; } err = 0; /* Initialize patterns */ memset(patt_FF, 0xFF, mtd->erasesize); for (i = 0; i < mtd->erasesize / pgsize; i++) { if (!(i & 1)) { memset(patt_5A5 + i * pgsize, 0x55, pgsize); memset(patt_A5A + i * pgsize, 0xAA, pgsize); } else { memset(patt_5A5 + i * pgsize, 0xAA, pgsize); memset(patt_A5A + i * pgsize, 0x55, pgsize); } } /* * Check if there is a bad eraseblock among those we are going to test. */ memset(&bad_ebs[0], 0, sizeof(int) * ebcnt); if (mtd->block_isbad) { for (i = eb; i < eb + ebcnt; i++) { err = mtd->block_isbad(mtd, (loff_t)i * mtd->erasesize); if (err < 0) { // printk(PRINT_PREF "block_isbad() returned %d " ; goto out; } if (err) { ; bad_ebs[i - eb] = 1; } } } start_timing(); while (1) { int i; void *patt; /* Erase all eraseblocks */ for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; err = erase_eraseblock(i); if (err) goto out; cond_resched(); } /* Check if the eraseblocks contain only 0xFF bytes */ if (check) { for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; err = check_eraseblock(i, patt_FF); if (err) { // printk(PRINT_PREF "verify failed" ; goto out; } cond_resched(); } } /* Write the pattern */ for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; if ((eb + erase_cycles) & 1) patt = patt_5A5; else patt = patt_A5A; err = write_pattern(i, patt); if (err) goto out; cond_resched(); } /* Verify what we wrote */ if (check) { for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; if ((eb + erase_cycles) & 1) patt = patt_5A5; else patt = patt_A5A; err = check_eraseblock(i, patt); if (err) { // printk(PRINT_PREF "verify failed for %s" // " pattern\n", // ((eb + erase_cycles) & 1) ? ; goto out; } cond_resched(); } } erase_cycles += 1; if (erase_cycles % gran == 0) { long ms; stop_timing(); ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; // printk(PRINT_PREF "%08u erase cycles done, took %lu " // "milliseconds (%lu seconds)\n", ; start_timing(); } if (!infinite && --cycles_count == 0) break; } out: // printk(PRINT_PREF "finished after %u erase cycles\n", ; kfree(check_buf); out_patt_FF: kfree(patt_FF); out_patt_A5A: kfree(patt_A5A); out_patt_5A5: kfree(patt_5A5); out_mtd: put_mtd_device(mtd); if (err) ; ; return err; }
static int __init tort_init(void) { int err = 0, i, infinite = !cycles_count; int bad_ebs[ebcnt]; printk(KERN_INFO "\n"); printk(KERN_INFO "=================================================\n"); printk(PRINT_PREF "Warning: this program is trying to wear out your " "flash, stop it if this is not wanted.\n"); printk(PRINT_PREF "MTD device: %d\n", dev); printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", ebcnt, eb, eb + ebcnt - 1, dev); if (pgcnt) printk(PRINT_PREF "torturing just %d pages per eraseblock\n", pgcnt); printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled"); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); printk(PRINT_PREF "error: cannot get MTD device\n"); return err; } if (mtd->writesize == 1) { printk(PRINT_PREF "not NAND flash, assume page size is 512 " "bytes.\n"); pgsize = 512; } else pgsize = mtd->writesize; if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt); goto out_mtd; } err = -ENOMEM; patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_5A5) { printk(PRINT_PREF "error: cannot allocate memory\n"); goto out_mtd; } patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_A5A) { printk(PRINT_PREF "error: cannot allocate memory\n"); goto out_patt_5A5; } patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_FF) { printk(PRINT_PREF "error: cannot allocate memory\n"); goto out_patt_A5A; } check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!check_buf) { printk(PRINT_PREF "error: cannot allocate memory\n"); goto out_patt_FF; } err = 0; /* Initialize patterns */ memset(patt_FF, 0xFF, mtd->erasesize); for (i = 0; i < mtd->erasesize / pgsize; i++) { if (!(i & 1)) { memset(patt_5A5 + i * pgsize, 0x55, pgsize); memset(patt_A5A + i * pgsize, 0xAA, pgsize); } else { memset(patt_5A5 + i * pgsize, 0xAA, pgsize); memset(patt_A5A + i * pgsize, 0x55, pgsize); } } /* * Check if there is a bad eraseblock among those we are going to test. */ memset(&bad_ebs[0], 0, sizeof(int) * ebcnt); if (mtd->block_isbad) { for (i = eb; i < eb + ebcnt; i++) { err = mtd->block_isbad(mtd, (loff_t)i * mtd->erasesize); if (err < 0) { printk(PRINT_PREF "block_isbad() returned %d " "for EB %d\n", err, i); goto out; } if (err) { printk("EB %d is bad. Skip it.\n", i); bad_ebs[i - eb] = 1; } } } start_timing(); while (1) { int i; void *patt; /* Erase all eraseblocks */ for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; err = erase_eraseblock(i); if (err) goto out; cond_resched(); } /* Check if the eraseblocks contain only 0xFF bytes */ if (check) { for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; err = check_eraseblock(i, patt_FF); if (err) { printk(PRINT_PREF "verify failed" " for 0xFF... pattern\n"); goto out; } cond_resched(); } } /* Write the pattern */ for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; if ((eb + erase_cycles) & 1) patt = patt_5A5; else patt = patt_A5A; err = write_pattern(i, patt); if (err) goto out; cond_resched(); } /* Verify what we wrote */ if (check) { for (i = eb; i < eb + ebcnt; i++) { if (bad_ebs[i - eb]) continue; if ((eb + erase_cycles) & 1) patt = patt_5A5; else patt = patt_A5A; err = check_eraseblock(i, patt); if (err) { printk(PRINT_PREF "verify failed for %s" " pattern\n", ((eb + erase_cycles) & 1) ? "0x55AA55..." : "0xAA55AA..."); goto out; } cond_resched(); } } erase_cycles += 1; if (erase_cycles % gran == 0) { long ms; stop_timing(); ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; printk(PRINT_PREF "%08u erase cycles done, took %lu " "milliseconds (%lu seconds)\n", erase_cycles, ms, ms / 1000); start_timing(); } if (!infinite && --cycles_count == 0) break; } out: printk(PRINT_PREF "finished after %u erase cycles\n", erase_cycles); kfree(check_buf); out_patt_FF: kfree(patt_FF); out_patt_A5A: kfree(patt_A5A); out_patt_5A5: kfree(patt_5A5); out_mtd: put_mtd_device(mtd); if (err) printk(PRINT_PREF "error %d occurred during torturing\n", err); printk(KERN_INFO "=================================================\n"); return err; }